You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
CubeSatSim/libs/libmf/source/wtimer.c

1022 lines
18 KiB

#include "ax8052.h"
#include "wtimer.h"
#define WTIMER0_MARGIN 0x1000
#define WTIMER1_MARGIN 0x1000
#define WTIMER_LPXOSC_SLEEP 8
struct wtimer_state __xdata wtimer_state[2];
struct wtimer_callback __xdata * __xdata wtimer_pending;
#if defined(SDCC)
static void dummy0(void) __naked
{
__asm;
.area HOME (CODE)
__endasm;
}
void wtimer_irq(void) __interrupt(1)
{
uint8_t __autodata dpssave = DPS;
uint8_t __autodata s = WTSTAT;
DPS = 0;
if (s & 0x01) {
wtimer0_update();
wtimer0_schedq();
s |= WTSTAT;
}
if (s & 0x20) {
wtimer1_update();
wtimer1_schedq();
WTSTAT;
}
DPS = dpssave;
}
static void dummy1(void) __naked
{
__asm;
.area CSEG (CODE)
__endasm;
}
#elif defined __CX51__ || defined __C51__
void wtimer_irq(void) interrupt 1
{
uint8_t __autodata dpssave = DPS;
uint8_t __autodata s = WTSTAT;
DPS = 0;
if (s & 0x01) {
wtimer0_update();
wtimer0_schedq();
s |= WTSTAT;
}
if (s & 0x20) {
wtimer1_update();
wtimer1_schedq();
WTSTAT;
}
DPS = dpssave;
}
#elif defined __ICC8051__
#pragma vector=0x0b
__interrupt void wtimer_irq(void)
{
uint8_t __autodata dpssave = DPS;
uint8_t __autodata s = WTSTAT;
DPS = 0;
if (s & 0x01) {
wtimer0_update();
wtimer0_schedq();
s |= WTSTAT;
}
if (s & 0x20) {
wtimer1_update();
wtimer1_schedq();
WTSTAT;
}
DPS = dpssave;
}
#else
#error "Compiler unsupported"
#endif
static __reentrantb void wtimer_doinit(uint8_t wakeup) __reentrant
{
IE_1 = 0;
wtimer_pending = WTIMER_NULLCB;
WTIRQEN = 0x21;
if (wakeup) {
if (SILICONREV == 0x8E && !(DBGLNKSTAT & 0x10))
wtimer_state[0].time.ref = 0;
wtimer0_update();
} else {
wtimer_state[0].time.ref = WTCNTA0;
wtimer_state[0].time.ref |= ((uint16_t)WTCNTR1) << 8;
wtimer_state[0].time.cur = 0;
wtimer_state[0].queue = WTIMER_NULLDESC;
}
wtimer_state[1].time.ref = WTCNTB0;
wtimer_state[1].time.ref |= ((uint16_t)WTCNTR1) << 8;
wtimer_state[1].time.cur = 0;
wtimer_state[1].queue = WTIMER_NULLDESC;
wtimer0_schedq();
wtimer1_schedq();
IE_1 = 1;
}
__reentrantb void wtimer_init(void) __reentrant
{
wtimer_doinit(PCON & 0x40);
}
__reentrantb void wtimer_init_deepsleep(void) __reentrant
{
wtimer_doinit(0);
}
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer_addcb_core(struct wtimer_callback __xdata *desc) __reentrant
{
struct wtimer_callback __xdata *d = WTIMER_CBPTR(wtimer_pending);
for (;;) {
struct wtimer_callback __xdata *dn = d->next;
if (dn == WTIMER_NULLCB)
break;
d = dn;
}
d->next = (struct wtimer_callback __xdata *)desc;
desc->next = WTIMER_NULLCB;
}
#if defined(WTIMER_USEASM) && defined(SDCC)
static void dummy2(void) __naked
{
__asm;
.area HOME (CODE)
__endasm;
}
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer0_schedq(void) __reentrant
{
__asm
;; check wtimer_state[0].queue != WTIMER_NULL
mov dptr,#(_wtimer_state + 0x0006)
movx a,@dptr
mov r6,a
inc dptr
movx a,@dptr
mov r7,a
cjne r6,#(WTIMER_NULL & 0xFF),00000$
cjne r7,#(WTIMER_NULL >> 8),00000$
00001$:
;; WTEVTA = wtimer_state[0].time.ref + (0x10000-WTIMER0_MARGIN)
mov dptr,#(_wtimer_state + 0x0004)
movx a,@dptr
add a,#((0x10000-WTIMER0_MARGIN) & 0xFF)
mov _WTEVTA0,a
inc dptr
movx a,@dptr
addc a,#((0x10000-WTIMER0_MARGIN) >> 8)
mov _WTEVTA1,a
ret
00000$:
;; R5:R4:R3:R2 = wtimer_state[0].time.cur - wtimer_state[0].queue->time;
mov dpl,r6
mov dph,r7
inc dptr
inc dptr
inc dptr
inc dptr
movx a,@dptr
mov r2,a
inc dptr
movx a,@dptr
mov r3,a
inc dptr
movx a,@dptr
mov r4,a
inc dptr
movx a,@dptr
mov r5,a
mov dptr,#(_wtimer_state + 0x0000)
movx a,@dptr
clr c
subb a,r2
mov r2,a
inc dptr
movx a,@dptr
subb a,r3
mov r3,a
inc dptr
movx a,@dptr
subb a,r4
mov r4,a
inc dptr
movx a,@dptr
subb a,r5
mov r5,a
jb acc.7,00002$
;; case R5:R4:R3:R2 >= 0
;; wtimer_state[0].queue = wtimer_state[0].queue->next
mov dpl,r6
mov dph,r7
movx a,@dptr
mov r2,a
inc dptr
movx a,@dptr
mov r3,a
mov dptr,#(_wtimer_state + 0x0006)
mov a,r2
movx @dptr,a
inc dptr
mov a,r3
movx @dptr,a
;; wtimer_addcb_core(old wtimer_state[0].queue)
mov dpl,r6
mov dph,r7
lcall _wtimer_addcb_core
sjmp _wtimer0_schedq
00002$:
;; check R5:R4:R3:R2 < -(0x10000-WTIMER0_MARGIN)
;; equivalent: (R5:R4:R3:R2 + (0x10000-WTIMER0_MARGIN)) < 0
mov a,r2
add a,#((0x10000-WTIMER0_MARGIN) & 0xFF)
mov a,r3
addc a,#((0x10000-WTIMER0_MARGIN) >> 8)
clr a
addc a,r4
clr a
addc a,r5
jb acc.7,00001$
;; WTEVTA = wtimer_state[0].time.ref - R3:R2
mov dptr,#(_wtimer_state + 0x0004)
movx a,@dptr
inc dptr
clr c
subb a,r2
mov _WTEVTA0,a
movx a,@dptr
subb a,r3
mov _WTEVTA1,a
ret
__endasm;
}
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer0_update(void) __reentrant __naked
{
__asm
mov r2,_WTCNTA0
mov r3,_WTCNTR1
mov dptr,#(_wtimer_state + 0x0004)
movx a,@dptr
xch a,r2
movx @dptr,a
inc dptr
clr c
subb a,r2
mov r2,a
movx a,@dptr
xch a,r3
movx @dptr,a
subb a,r3
mov r3,a
orl a,ar2
jz 00000$
mov dptr,#(_wtimer_state + 0x0000)
movx a,@dptr
add a,r2
movx @dptr,a
inc dptr
movx a,@dptr
addc a,r3
movx @dptr,a
inc dptr
movx a,@dptr
addc a,#0
movx @dptr,a
inc dptr
movx a,@dptr
addc a,#0
movx @dptr,a
00000$: ret
__endasm;
}
static void dummy3(void) __naked
{
__asm;
.area CSEG (CODE)
__endasm;
}
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer0_addcore(struct wtimer_desc __xdata *desc) __reentrant __naked
{
__asm
;; R5:R4 = &wtimer_state[0].queue
mov r4,#(_wtimer_state + 0x0006)
mov r5,#((_wtimer_state + 0x0006) >> 8)
_wtimer_addcore:
;; R3:R2 = desc
mov r2,dpl
mov r3,dph
00000$:
;; R7:R6 = R5:R4->next
mov dpl,r4
mov dph,r5
movx a,@dptr
mov r6,a
inc dptr
movx a,@dptr
mov r7,a
;; check R7:R6 != WTIMER_NULL
cjne r6,#(WTIMER_NULL & 0xFF),00002$
cjne r7,#(WTIMER_NULL >> 8),00002$
00001$:
;; R3:R2->next = R7:R6
mov dpl,r2
mov dph,r3
mov a,r6
movx @dptr,a
inc dptr
mov a,r7
movx @dptr,a
;; R5:R4->next = R3:R2
mov dpl,r4
mov dph,r5
mov a,r2
movx @dptr,a
inc dptr
mov a,r3
movx @dptr,a
ret
00002$:
;; A.7 = sign (R3:R2->time - R7:R6->time)
push ar6
push ar7
mov dpl,r6
mov dph,r7
inc dptr
inc dptr
inc dptr
inc dptr
movx a,@dptr
mov r0,a
inc dptr
movx a,@dptr
mov r1,a
inc dptr
movx a,@dptr
mov r6,a
inc dptr
movx a,@dptr
mov r7,a
mov dpl,r2
mov dph,r3
inc dptr
inc dptr
inc dptr
inc dptr
clr c
movx a,@dptr
subb a,r0
inc dptr
movx a,@dptr
subb a,r1
inc dptr
movx a,@dptr
subb a,r6
inc dptr
movx a,@dptr
subb a,r7
jb acc.7,00003$
pop ar5
pop ar4
sjmp 00000$
00003$:
pop ar7
pop ar6
sjmp 00001$
__endasm;
}
static void dummy4(void) __naked
{
__asm;
.area HOME (CODE)
__endasm;
}
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer1_schedq(void) __reentrant
{
__asm
;; check wtimer_state[1].queue != WTIMER_NULL
mov dptr,#(_wtimer_state + 0x000E)
movx a,@dptr
mov r6,a
inc dptr
movx a,@dptr
mov r7,a
cjne r6,#(WTIMER_NULL & 0xFF),00000$
cjne r7,#(WTIMER_NULL >> 8),00000$
00001$:
;; WTEVTB = wtimer_state[1].time.ref + (0x10000-WTIMER1_MARGIN)
mov dptr,#(_wtimer_state + 0x000C)
movx a,@dptr
add a,#((0x10000-WTIMER1_MARGIN) & 0xFF)
mov _WTEVTB0,a
inc dptr
movx a,@dptr
addc a,#((0x10000-WTIMER1_MARGIN) >> 8)
mov _WTEVTB1,a
ret
00000$:
;; R5:R4:R3:R2 = wtimer_state[1].time.cur - wtimer_state[1].queue->time;
mov dpl,r6
mov dph,r7
inc dptr
inc dptr
inc dptr
inc dptr
movx a,@dptr
mov r2,a
inc dptr
movx a,@dptr
mov r3,a
inc dptr
movx a,@dptr
mov r4,a
inc dptr
movx a,@dptr
mov r5,a
mov dptr,#(_wtimer_state + 0x0008)
movx a,@dptr
clr c
subb a,r2
mov r2,a
inc dptr
movx a,@dptr
subb a,r3
mov r3,a
inc dptr
movx a,@dptr
subb a,r4
mov r4,a
inc dptr
movx a,@dptr
subb a,r5
mov r5,a
jb acc.7,00002$
;; case R5:R4:R3:R2 >= 0
;; wtimer_state[1].queue = wtimer_state[1].queue->next
mov dpl,r6
mov dph,r7
movx a,@dptr
mov r2,a
inc dptr
movx a,@dptr
mov r3,a
mov dptr,#(_wtimer_state + 0x000E)
mov a,r2
movx @dptr,a
inc dptr
mov a,r3
movx @dptr,a
;; wtimer_addcb_core(old wtimer_state[1].queue)
mov dpl,r6
mov dph,r7
lcall _wtimer_addcb_core
sjmp _wtimer1_schedq
00002$:
;; check R5:R4:R3:R2 < -(0x10000-WTIMER1_MARGIN)
;; equivalent: (R5:R4:R3:R2 + (0x10000-WTIMER1_MARGIN)) < 0
mov a,r2
add a,#((0x10000-WTIMER1_MARGIN) & 0xFF)
mov a,r3
addc a,#((0x10000-WTIMER1_MARGIN) >> 8)
clr a
addc a,r4
clr a
addc a,r5
jb acc.7,00001$
;; WTEVTB = wtimer_state[1].time.ref - R3:R2
mov dptr,#(_wtimer_state + 0x000C)
movx a,@dptr
inc dptr
clr c
subb a,r2
mov _WTEVTB0,a
movx a,@dptr
subb a,r3
mov _WTEVTB1,a
ret
__endasm;
}
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer1_update(void) __reentrant __naked
{
__asm
mov r2,_WTCNTB0
mov r3,_WTCNTR1
mov dptr,#(_wtimer_state + 0x000C)
movx a,@dptr
xch a,r2
movx @dptr,a
inc dptr
clr c
subb a,r2
mov r2,a
movx a,@dptr
xch a,r3
movx @dptr,a
subb a,r3
mov r3,a
orl a,ar2
jz 00000$
mov dptr,#(_wtimer_state + 0x0008)
movx a,@dptr
add a,r2
movx @dptr,a
inc dptr
movx a,@dptr
addc a,r3
movx @dptr,a
inc dptr
movx a,@dptr
addc a,#0
movx @dptr,a
inc dptr
movx a,@dptr
addc a,#0
movx @dptr,a
00000$: ret
__endasm;
}
static void dummy5(void) __naked
{
__asm;
.area CSEG (CODE)
__endasm;
}
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer1_addcore(struct wtimer_desc __xdata *desc) __reentrant __naked
{
__asm
;; R5:R4 = &wtimer_state[1].queue
mov r4,#(_wtimer_state + 0x000E)
mov r5,#((_wtimer_state + 0x000E) >> 8)
ljmp _wtimer_addcore
__endasm;
}
static void wtimer_preparesleep(void) __naked
{
__asm
mov _WTCFGB,#0x0F
mov _WTIRQEN,#0x01
mov dptr,#_SILICONREV
movx a,@dptr
cjne a,#0x8E,00000$
;; R3:R2 = WTEVTA - wtimer_state[0].time.ref
;; wtimer_state[0].time.ref = WTEVTA
mov dptr,#(_wtimer_state + 0x0004)
mov r2,_WTEVTA0
movx a,@dptr
xch a,r2
movx @dptr,a
clr c
subb a,r2
mov r2,a
inc dptr
mov r3,_WTEVTA1
movx a,@dptr
xch a,r3
movx @dptr,a
subb a,r3
mov r3,a
mov r4,#0
;; check for LPXOSC source
mov a,_DBGLNKSTAT
anl a,#0x10
jnz 00001$
mov a,_WTCFGA
anl a,#0x07
cjne a,#CLKSRC_LPXOSC,00001$
mov a,_WTCFGA
swap a
rl a
anl a,#0x07
inc a
mov r4,a
mov a,#((WTIMER_LPXOSC_SLEEP) << 2)
00002$:
clr c
rrc a
djnz r4,00002$
add a,r2
mov r2,a
clr a
addc a,r3
mov r3,a
clr a
addc a,r4
mov r4,a
00001$:
;; wtimer_state[0].time.cur += R4:R3:R2
mov dptr,#(_wtimer_state + 0x0000)
movx a,@dptr
add a,r2
movx @dptr,a
inc dptr
movx a,@dptr
addc a,r3
movx @dptr,a
inc dptr
movx a,@dptr
addc a,r4
movx @dptr,a
inc dptr
movx a,@dptr
addc a,#0
movx @dptr,a
00000$:
ret
__endasm;
}
static uint8_t wtimer_checkexpired(void) __naked
{
__asm
;; R3:R2 = WTEVTA1:WTEVTA0 - WTCNTR1:WTCNTA0 - 1
setb c
mov a,_WTEVTA0
subb a,_WTCNTA0
mov r2,a
mov a,_WTEVTA1
subb a,_WTCNTR1
mov r3,a
;; R3:R2 + WTIMER0_MARGIN
.if (WTIMER0_MARGIN & 0xFF)
mov a,#(WTIMER0_MARGIN & 0xFF)
add a,r2
mov a,#(WTIMER0_MARGIN >> 8)
addc a,r3
.else
mov a,#(WTIMER0_MARGIN >> 8)
add a,r3
.endif
jc 00000$
;; R3:R2 = WTEVTB1:WTEVTB0 - WTCNTR1:WTCNTB0 - 1
setb c
mov a,_WTEVTB0
subb a,_WTCNTB0
mov r2,a
mov a,_WTEVTB1
subb a,_WTCNTR1
mov r3,a
;; R3:R2 + WTIMER1_MARGIN
.if (WTIMER1_MARGIN & 0xFF)
mov a,#(WTIMER1_MARGIN & 0xFF)
add a,r2
mov a,#(WTIMER1_MARGIN >> 8)
addc a,r3
.else
mov a,#(WTIMER1_MARGIN >> 8)
add a,r3
.endif
jc 00000$
;; check WTSTAT & 0x21
mov a,_WTSTAT
anl a,#0x21
jnz 00000$
mov dpl,a
ret
00000$:
mov dpl,#1
ret
__endasm;
}
#else
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer0_schedq(void) __reentrant
{
while (wtimer_state[0].queue != WTIMER_NULLDESC) {
int32_t __autodata td = wtimer_state[0].time.cur - wtimer_state[0].queue->time;
if (td >= 0) {
struct wtimer_callback __xdata * __autodata d = (struct wtimer_callback __xdata *)wtimer_state[0].queue;
wtimer_state[0].queue = wtimer_state[0].queue->next;
wtimer_addcb_core(d);
continue;
}
if (td < -(0x10000-WTIMER0_MARGIN))
break;
{
uint16_t __autodata nxt = wtimer_state[0].time.ref - (uint16_t)td;
WTEVTA0 = nxt;
WTEVTA1 = nxt >> 8;
}
return;
}
{
uint16_t __autodata nxt = wtimer_state[0].time.ref + (uint16_t)(0x10000-WTIMER0_MARGIN);
WTEVTA0 = nxt;
WTEVTA1 = nxt >> 8;
}
}
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer0_update(void) __reentrant
{
uint16_t __autodata t;
t = WTCNTA0;
t |= ((uint16_t)WTCNTR1) << 8;
{
uint16_t __autodata t1 = wtimer_state[0].time.ref;
wtimer_state[0].time.ref = t;
t -= t1;
}
if (!t)
return;
wtimer_state[0].time.cur += t;
}
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer0_addcore(struct wtimer_desc __xdata *desc) __reentrant
{
struct wtimer_desc __xdata * __autodata d = WTIMER_PTR(wtimer_state[0].queue);
for (;;) {
struct wtimer_desc __xdata * __autodata dn = d->next;
int32_t __autodata td;
if (dn == WTIMER_NULLDESC)
break;
td = desc->time - dn->time;
if (td < 0)
break;
d = dn;
}
desc->next = d->next;
d->next = desc;
}
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer1_schedq(void) __reentrant
{
while (wtimer_state[1].queue != WTIMER_NULLDESC) {
int32_t __autodata td = wtimer_state[1].time.cur - wtimer_state[1].queue->time;
if (td >= 0) {
struct wtimer_callback __xdata * __autodata d = (struct wtimer_callback __xdata *)wtimer_state[1].queue;
wtimer_state[1].queue = wtimer_state[1].queue->next;
wtimer_addcb_core(d);
continue;
}
if (td < -(0x10000-WTIMER1_MARGIN))
break;
{
uint16_t __autodata nxt = wtimer_state[1].time.ref - (uint16_t)td;
WTEVTB0 = nxt;
WTEVTB1 = nxt >> 8;
}
return;
}
{
uint16_t __autodata nxt = wtimer_state[1].time.ref + (uint16_t)(0x10000-WTIMER1_MARGIN);
WTEVTB0 = nxt;
WTEVTB1 = nxt >> 8;
}
}
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer1_update(void) __reentrant
{
uint16_t __autodata t;
t = WTCNTB0;
t |= ((uint16_t)WTCNTR1) << 8;
{
uint16_t __autodata t1 = wtimer_state[1].time.ref;
wtimer_state[1].time.ref = t;
t -= t1;
}
if (!t)
return;
wtimer_state[1].time.cur += t;
}
// Must be called with (wtimer) interrupts disabled
__reentrantb void wtimer1_addcore(struct wtimer_desc __xdata *desc) __reentrant
{
struct wtimer_desc __xdata * __autodata d = WTIMER_PTR(wtimer_state[1].queue);
for (;;) {
struct wtimer_desc __xdata * __autodata dn = d->next;
int32_t __autodata td;
if (dn == WTIMER_NULLDESC)
break;
td = desc->time - dn->time;
if (td < 0)
break;
d = dn;
}
desc->next = d->next;
d->next = desc;
}
static __reentrantb void wtimer_preparesleep(void) __reentrant
{
uint16_t __autodata t;
WTCFGB = 0x0F;
WTIRQEN = 0x01;
if (SILICONREV != 0x8E)
return;
t = WTEVTA0;
t |= ((uint16_t)WTEVTA1) << 8;
{
uint16_t t1 = wtimer_state[0].time.ref;
wtimer_state[0].time.ref = t;
t -= t1;
}
if (!(DBGLNKSTAT & 0x10))
if ((WTCFGA & 0x07) == CLKSRC_LPXOSC)
t += (((uint8_t)(WTIMER_LPXOSC_SLEEP)) << 1) >> ((WTCFGA >> 3) & 0x07);
wtimer_state[0].time.cur += t;
}
static __reentrantb uint8_t wtimer_checkexpired(void) __reentrant
{
{
uint16_t __autodata t;
t = WTCNTA0;
t |= ((uint16_t)WTCNTR1) << 8;
t -= WTEVTA0 | (((uint16_t)WTEVTA1) << 8);
if (t < WTIMER0_MARGIN)
return 1;
}
{
uint16_t __autodata t;
t = WTCNTB0;
t |= ((uint16_t)WTCNTR1) << 8;
t -= WTEVTB0 | (((uint16_t)WTEVTB1) << 8);
if (t < WTIMER1_MARGIN)
return 1;
}
if (WTSTAT & 0x21)
return 1;
return 0;
}
#endif
#if defined(SDCC)
extern __reentrantb uint8_t wtimer_cansleep(void) __reentrant;
static void wtimer_cansleep_dummy(void) __naked
{
__asm
.area HOME (CODE)
.area WTCANSLP0 (CODE)
.area WTCANSLP1 (CODE)
.area WTCANSLP2 (CODE)
.area WTCANSLP0 (CODE)
_wtimer_cansleep_ret0:
mov dpl,#0x00
ret
.globl _wtimer_cansleep
_wtimer_cansleep:
;; wtimer_state[1].queue == WTIMER_NULLDESC
mov dptr,#(_wtimer_state + 0x000e)
movx a,@dptr
cpl a
jnz _wtimer_cansleep_ret0
inc dptr
movx a,@dptr
cpl a
jnz _wtimer_cansleep_ret0
.area WTCANSLP2 (CODE)
mov dpl,#0x01
ret
.area HOME (CODE)
.area WTSTDBY0 (CODE)
.area WTSTDBY1 (CODE)
.area WTSTDBY2 (CODE)
.area WTSTDBY1 (CODE)
push ar0
push ar1
push ar2
push ar3
push ar4
push ar5
push ar6
push ar7
lcall _wtimer_runcallbacks
mov dpl,#WTFLAG_CANSTANDBY
lcall _wtimer_idle
pop ar7
pop ar6
pop ar5
pop ar4
pop ar3
pop ar2
pop ar1
pop ar0
ret
.area CSEG (CODE)
__endasm;
}
#else
__reentrantb uint8_t wtimer_cansleep(void) __reentrant
{
return wtimer_state[1].queue == WTIMER_NULLDESC;
}
#endif
#if defined(SDCC)
typedef __reentrantb void (*handler_t)(struct wtimer_callback __xdata *desc) __reentrant;
#else
typedef void (*handler_t)(struct wtimer_callback __xdata *desc);
#endif
/*
* This function is reentrant even though it is not marked reentrant.
* When marked reentrant, code generation gets worse for SDCC
* (IE is placed on stack rather than a register)
*/
#if defined(SDCC)
#pragma nooverlay wtimer_runcallbacks
uint8_t wtimer_runcallbacks(void)
#elif defined(__ICC8051__)
uint8_t wtimer_runcallbacks(void)
#else
__reentrantb uint8_t wtimer_runcallbacks(void) __reentrant
#endif
{
uint8_t __autodata ret = 0;
for (;;) {
uint8_t __autodata iesave = IE & 0x80;
EA = 0;
wtimer0_update();
wtimer0_schedq();
wtimer1_update();
wtimer1_schedq();
for (;;) {
{
struct wtimer_callback __xdata * __autodata d = wtimer_pending;
if (d != WTIMER_NULLCB) {
wtimer_pending = d->next;
IE |= iesave;
++ret;
((handler_t)(d->handler))(d);
EA = 0;
continue;
}
}
{
uint8_t __autodata exp = wtimer_checkexpired();
IE |= iesave;
if (exp)
break;
return ret;
}
}
}
}
#if defined(SDCC) || defined(__ICC8051__)
#define WTFLAG_CANSLEEPANY (WTFLAG_CANSLEEP | WTFLAG_CANSLEEPCONT)
#else
#define WTFLAG_CANSLEEPANY (WTFLAG_CANSLEEP)
#endif
__reentrantb uint8_t wtimer_idle(uint8_t flags) __reentrant
{
uint8_t iesave = IE & 0x80;
EA = 0;
if (wtimer_pending != WTIMER_NULLCB || wtimer_checkexpired()) {
IE |= iesave;
return WTIDLE_WORK;
}
if (flags & WTFLAG_CANSLEEPANY && wtimer_cansleep()) {
wtimer_preparesleep();
// FIXME: copy wtimer_state[0] to IRAM if there are not too many cb's?
if ((void __xdata *)(&wtimer_state[0]) < (void __xdata *)0x1000)
PCON = (PCON & 0x0C) | 0x04;
if ((void __xdata *)(&wtimer_state[0]) >= (void __xdata *)(0x1000-sizeof(wtimer_state[0])))
PCON = (PCON & 0x0C) | 0x08;
#if defined(SDCC) || defined(__ICC8051__)
if (flags & WTFLAG_CANSLEEPCONT) {
enter_sleep_cont();
IE |= iesave;
return WTIDLE_SLEEP;
}
#endif
enter_sleep();
} else if (flags & WTFLAG_CANSTANDBY) {
enter_standby();
}
IE |= iesave;
return 0;
}

Powered by TurnKey Linux.