# HG changeset patch # User Edouard Tisserant # Date 1567505853 -7200 # Node ID 31785529a65788c1218ecd0e2b63f1d7900a2d34 # Parent 302347f481937af9347a4334bde3ec54c43b6faf SVGHMI: Intermediate state while working on svghmi.c diff -r 302347f48193 -r 31785529a657 svghmi/svghmi.c --- a/svghmi/svghmi.c Mon Aug 26 08:54:02 2019 +0200 +++ b/svghmi/svghmi.c Tue Sep 03 12:17:33 2019 +0200 @@ -4,6 +4,7 @@ #include "config.h" #include "beremiz.h" +#define DEFAULT_REFRESH_PERIOD_MS 100 #define HMI_BUFFER_SIZE %(buffer_size)d /* PLC reads from that buffer */ @@ -12,16 +13,38 @@ /* PLC writes to that buffer */ static char wbuf[HMI_BUFFER_SIZE]; -static pthread_mutex_t wbuf_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t rbuf_mutex = PTHREAD_MUTEX_INITIALIZER; +%(extern_variables_declarations)s -%(extern_variables_declarations)s +#define ticktime_ns %(PLC_ticktime)d; +uint16_t ticktime_ms (ticktime_ns>1000000)? + ticktime_ns/1000000: + 1; + +typedef enum { + buf_free = 0, + buf_set, + buf_tosend +} buf_state_t; + +int global_write_dirty = 0; typedef const struct { void *ptr; __IEC_types_enum type; uint32_t buf_index; - uint32_t flags; + + /* publish/write/send */ + int wlock; + /* zero means not subscribed */ + uint16_t refresh_period_ms; + uint16_t age_ms; + + buf_state_t wstate; + + /* retrieve/read/recv */ + int rlock; + buf_state_t rstate; + } hmi_tree_item_t; static hmi_tree_item_t hmi_tree_item[] = { @@ -51,7 +74,56 @@ void *visible_value_p = UnpackVar(dsc, &real_value_p, &flags); - memcpy(dest_p, visible_value_p, __get_type_enum_size(dsc->type)); + /* Try take lock */ + long was_locked = AtomicCompareExchange(&dsc->wlock, 0, 1); + + if(was_locked) { + /* was locked. give up*/ + return; + } + + if(dsc->wstate == buf_set) + /* if being subscribed */ + if(dsc->refresh_period_ms){ + if(dsc->age_ms + ticktime_ms < dsc->refresh_period_ms){ + dsc->age_ms += ticktime_ms; + }else{ + dsc->wstate = buf_tosend; + } + } + } + + /* if new value differs from previous one */ + if(memcmp(dest_p, visible_value_p, __get_type_enum_size(dsc->type)) != 0){ + /* copy and flag as set */ + memcpy(dest_p, visible_value_p, __get_type_enum_size(dsc->type)); + if(dsc->wstate == buf_free) { + dsc->wstate = buf_set; + dsc->age_ms = 0; + } + global_write_dirty = 1; + } + + /* unlock - use AtomicComparExchange to have memory barrier */ + AtomicCompareExchange(&dsc->wlock, 1, 0); +} + +struct timespec sending_now; +struct timespec next_sending; +void send_iterator(hmi_tree_item_t *dsc) +{ + while(AtomicCompareExchange(&dsc->wlock, 0, 1)) sched_yield(); + + // check for variable being modified + if(dsc->wstat == buf_tosend){ + // send + + // TODO write to some socket + + dsc->wstate = buf_free; + } + + AtomicCompareExchange(&dsc->wlock, 1, 0); } void read_iterator(hmi_tree_item_t *dsc) @@ -62,6 +134,7 @@ void *visible_value_p = UnpackVar(dsc, &real_value_p, &flags); + memcpy(visible_value_p, src_p, __get_type_enum_size(dsc->type)); } @@ -69,6 +142,11 @@ { bzero(rbuf,sizeof(rbuf)); bzero(wbuf,sizeof(wbuf)); + + // create - connection endpoint + // - sending thread + // - sending semaphore + // - recv thread return 0; } @@ -79,16 +157,24 @@ void __retrieve_svghmi() { - if(!pthread_mutex_lock(&rbuf_mutex)){ - traverse_hmi_tree(read_iterator); - pthread_mutex_unlock(&rbuf_mutex); - } + traverse_hmi_tree(read_iterator); } void __publish_svghmi() { - if(!pthread_mutex_lock(&wbuf_mutex)){ - pthread_mutex_unlock(&wbuf_mutex); + global_write_dirty = 0; + traverse_hmi_tree(write_iterator); + if(global_write_dirty) { + // TODO : set emaphore to wakeup sending thread } + } +void sending_thread_proc(void* args){ + + // TODO : wait for + // - semaphore + // - next autonomous send thread wakeup. (impl as wait timeout ?) + + traverse_hmi_tree(send_iterator); +} diff -r 302347f48193 -r 31785529a657 svghmi/svghmi.py --- a/svghmi/svghmi.py Mon Aug 26 08:54:02 2019 +0200 +++ b/svghmi/svghmi.py Tue Sep 03 12:17:33 2019 +0200 @@ -181,7 +181,7 @@ "OUT": "_O_ENUM", "VAR": "_ENUM" }[node.vartype] + ", " + - str(buf_index) + ", 0}"] + str(buf_index) + ", 0, }"] buf_index += sz if len(node.path) == 1: extern_variables_declarations += [ @@ -208,7 +208,8 @@ "variable_decl_array": ",\n".join(variable_decl_array), "extern_variables_declarations": "\n".join(extern_variables_declarations), "buffer_size": buf_index, - "var_access_code": targets.GetCode("var_access.c") + "var_access_code": targets.GetCode("var_access.c"), + "PLC_ticktime": self.GetCTRoot().GetTicktime() } gen_svghmi_c_path = os.path.join(buildpath, "svghmi.c")