Change the run_timers execution frequency

We now use the GCD of all the async timers.
This commit is contained in:
jeltz 2021-01-18 03:47:58 +01:00
parent a6f60bbf4e
commit 545e31c6f9
Signed by: jeltz
GPG key ID: 800882B66C0C3326
5 changed files with 34 additions and 14 deletions

View file

@ -49,6 +49,8 @@ struct
let fold_lcm l = List.fold_left lcm (List.hd l) (List.tl l)
let fold_gcd l = List.fold_left gcd (List.hd l) (List.tl l)
let ms_of_ack = function
| Timer_ms ms -> ms
@ -58,34 +60,37 @@ struct
let incr = Cbop ("+", Cvar name, one_const) in
Caffect (CLvar name, Cbop ("%", incr, modulo_const))
let call_step_async tick_var (od, ack) =
let call_step_async tick_var base (od, ack) =
let step = (cname_of_qn od.o_class) ^ "_async_step" in
let global = async_global_var_name od in
let call = Csexpr (Cfun_call (step, [Caddrof (Cvar global)])) in
let zero = Cconst (Ccint 0) in
let timer = Cconst (Ccint (ms_of_ack ack)) in
let timer = Cconst (Ccint (ms_of_ack ack / base)) in
let cond = Cbop ("==", Cbop ("%", tick_var, timer), zero) in
Cif (cond, [call], [])
let decls_and_defs objs =
let trans = List.map
let translate_objs objs =
List.map
(fun od ->
let ack = Option.get od.o_ack in
(od, translate_ack ack))
objs
in
let decls_and_defs objs =
let trans = translate_objs objs in
let timers = List.map
(fun (_, ack) -> match ack with Timer_ms ms -> ms)
(fun (_, ack) -> ms_of_ack ack)
trans
in
let body = match timers with
| [] -> []
| _ ->
let gcd_timer = fold_gcd timers in
let lcm_timer = fold_lcm timers in
let steps =
List.map (call_step_async (Cvar "tick")) trans
List.map (call_step_async (Cvar "tick") gcd_timer) trans
in
let incr = incr_mod "tick" lcm_timer in
let incr = incr_mod "tick" (lcm_timer / gcd_timer) in
steps @ [incr]
in
(* run_timers is declared in avr.h (because of the ISR macro which
@ -105,6 +110,16 @@ struct
] in
[], defs
let main_init = [Csexpr (Cfun_call ("init_timer1", []))]
let main_init objs =
let trans = translate_objs objs in
let timers = List.map
(fun (_, ack) -> ms_of_ack ack)
trans
in
match timers with
| [] -> []
| _ ->
let value = fold_gcd timers in
[Csexpr (Cfun_call ("init_timer1", [Cconst (Ccint value)]))]
end

View file

@ -7,5 +7,5 @@ sig
val gen_copy_func_out : class_def -> cdef
val includes : string list
val decls_and_defs : obj_dec list -> cdecl list * cdef list
val main_init : cstm list
val main_init : obj_dec list -> cstm list
end

View file

@ -418,7 +418,10 @@ let mk_main name p =
* could be triggered while the initial reset of the async nodes is
* not yet terminated.
*)
let res_l = res_l @ AvrBackend.main_init in
let async_objs = List.flatten
(List.map filter_async_objs classes)
in
let res_l = res_l @ AvrBackend.main_init async_objs in
[("_main.c", Csource (defs @ [main_skel var_l res_l step_l]));
("_main.h", Cheader ([name], []))];

View file

@ -30,6 +30,7 @@
#include <util/atomic.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <assert.h>
#include "avr.h"
ISR(TIMER1_COMPA_vect) {
@ -42,9 +43,10 @@ static inline void set_ocr1a(uint16_t value) {
}
/* Source: https://adnbr.co.uk/articles/counting-milliseconds */
void init_timer1() {
void init_timer1(unsigned int ms) {
assert(ms < 1000);
TCCR1B |= _BV(WGM12) | _BV(CS11);
set_ocr1a((F_CPU / 1000) / 8);
set_ocr1a(((ms * F_CPU) / 1000) / 8);
TIMSK1 |= _BV(OCIE1A);
sei();
}

View file

@ -39,7 +39,7 @@
void run_timers();
void init_timer1();
void init_timer1(unsigned int ms);
void atomic_memcpy(void *dest, const void *src, size_t size);