sched: Be explicit with loading of the waketime variable
Explicilty load the timer waketime variable into local variables in sched_timer_kick(). Change the optimization level from Os to O2. This helps gcc to avoid unnecessary reloads from memory in the common stepper_event() case. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
4dfa6c6ee4
commit
59b71d5d05
|
@ -5,7 +5,7 @@ CROSS_PREFIX=avr-
|
||||||
|
|
||||||
dirs-y += src/avr lib/pjrc_usb_serial
|
dirs-y += src/avr lib/pjrc_usb_serial
|
||||||
|
|
||||||
CFLAGS-y += -Os -mmcu=$(CONFIG_MCU) -DF_CPU=$(CONFIG_CLOCK_FREQ)
|
CFLAGS-y += -O2 -mmcu=$(CONFIG_MCU) -DF_CPU=$(CONFIG_CLOCK_FREQ)
|
||||||
LDFLAGS-y += -Wl,--relax
|
LDFLAGS-y += -Wl,--relax
|
||||||
|
|
||||||
# Add avr source files
|
# Add avr source files
|
||||||
|
|
|
@ -153,7 +153,7 @@ timer_periodic(void)
|
||||||
// if the next timer is too close to schedule. Caller must disable
|
// if the next timer is too close to schedule. Caller must disable
|
||||||
// irqs.
|
// irqs.
|
||||||
uint8_t
|
uint8_t
|
||||||
timer_try_set_next(uint32_t target)
|
timer_try_set_next(unsigned int target)
|
||||||
{
|
{
|
||||||
uint16_t next = target;
|
uint16_t next = target;
|
||||||
int16_t diff = next - timer_get();
|
int16_t diff = next - timer_get();
|
||||||
|
|
|
@ -13,7 +13,7 @@ uint32_t timer_from_us(uint32_t us);
|
||||||
uint8_t timer_is_before(uint32_t time1, uint32_t time2);
|
uint8_t timer_is_before(uint32_t time1, uint32_t time2);
|
||||||
uint32_t timer_read_time(void);
|
uint32_t timer_read_time(void);
|
||||||
void timer_periodic(void);
|
void timer_periodic(void);
|
||||||
uint8_t timer_try_set_next(uint32_t next);
|
uint8_t timer_try_set_next(unsigned int next);
|
||||||
|
|
||||||
size_t alloc_maxsize(size_t reqsize);
|
size_t alloc_maxsize(size_t reqsize);
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ static uint32_t timer_repeat_until;
|
||||||
// if the next timer is too close to schedule. Caller must disable
|
// if the next timer is too close to schedule. Caller must disable
|
||||||
// irqs.
|
// irqs.
|
||||||
uint8_t
|
uint8_t
|
||||||
timer_try_set_next(uint32_t next)
|
timer_try_set_next(unsigned int next)
|
||||||
{
|
{
|
||||||
uint32_t now = timer_read_time();
|
uint32_t now = timer_read_time();
|
||||||
int32_t diff = next - now;
|
int32_t diff = next - now;
|
||||||
|
|
42
src/sched.c
42
src/sched.c
|
@ -122,55 +122,55 @@ sched_del_timer(struct timer *del)
|
||||||
irq_restore(flag);
|
irq_restore(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move a rescheduled timer to its new location in the list. Returns
|
// Move a rescheduled timer to its new location in the list.
|
||||||
// the next timer to run.
|
static void
|
||||||
static struct timer *
|
reschedule_timer(struct timer *t, uint32_t updated_waketime)
|
||||||
reschedule_timer(struct timer *t)
|
|
||||||
{
|
{
|
||||||
uint32_t waketime = t->waketime;
|
|
||||||
struct timer *pos = t->next;
|
|
||||||
if (timer_is_before(waketime, pos->waketime))
|
|
||||||
// Timer is still the first - no insertion needed
|
|
||||||
return t;
|
|
||||||
|
|
||||||
// Find new timer position and update list
|
// Find new timer position and update list
|
||||||
|
struct timer *pos = t->next, *prev;
|
||||||
timer_list = pos;
|
timer_list = pos;
|
||||||
struct timer *prev;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
prev = pos;
|
prev = pos;
|
||||||
if (CONFIG_MACH_AVR)
|
if (CONFIG_MACH_AVR)
|
||||||
// micro optimization for AVR - reduces register pressure
|
// micro optimization for AVR - reduces register pressure
|
||||||
asm("" : "+r"(prev) : : "memory");
|
asm("" : "+r"(prev));
|
||||||
pos = pos->next;
|
pos = pos->next;
|
||||||
if (timer_is_before(waketime, pos->waketime))
|
if (timer_is_before(updated_waketime, pos->waketime))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t->next = pos;
|
t->next = pos;
|
||||||
prev->next = t;
|
prev->next = t;
|
||||||
return timer_list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoke timers - called from board timer irq code.
|
// Invoke timers - called from board timer irq code.
|
||||||
void
|
void
|
||||||
sched_timer_kick(void)
|
sched_timer_kick(void)
|
||||||
{
|
{
|
||||||
struct timer *t = timer_list;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Invoke timer callback
|
// Invoke timer callback
|
||||||
|
struct timer *t = timer_list;
|
||||||
uint_fast8_t res;
|
uint_fast8_t res;
|
||||||
if (CONFIG_INLINE_STEPPER_HACK && likely(!t->func))
|
uint32_t updated_waketime;
|
||||||
|
if (CONFIG_INLINE_STEPPER_HACK && likely(!t->func)) {
|
||||||
res = stepper_event(t);
|
res = stepper_event(t);
|
||||||
else
|
updated_waketime = t->waketime;
|
||||||
|
} else {
|
||||||
res = t->func(t);
|
res = t->func(t);
|
||||||
|
updated_waketime = t->waketime;
|
||||||
|
}
|
||||||
|
|
||||||
// Update timer_list (rescheduling current timer if necessary)
|
// Update timer_list (rescheduling current timer if necessary)
|
||||||
if (unlikely(res == SF_DONE))
|
unsigned int next_waketime = updated_waketime;
|
||||||
|
if (unlikely(res == SF_DONE)) {
|
||||||
t = timer_list = t->next;
|
t = timer_list = t->next;
|
||||||
else
|
next_waketime = t->waketime;
|
||||||
t = reschedule_timer(t);
|
} else if (!timer_is_before(updated_waketime, t->next->waketime)) {
|
||||||
|
next_waketime = t->next->waketime;
|
||||||
|
reschedule_timer(t, updated_waketime);
|
||||||
|
}
|
||||||
|
|
||||||
// Schedule next timer event (or run next timer if it's ready)
|
// Schedule next timer event (or run next timer if it's ready)
|
||||||
res = timer_try_set_next(t->waketime);
|
res = timer_try_set_next(next_waketime);
|
||||||
if (res)
|
if (res)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ timer_read_time(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
timer_try_set_next(uint32_t next)
|
timer_try_set_next(unsigned int next)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue