svghmi/svghmi.c
changeset 3374 9a82918e063c
parent 3295 0375d801fff7
child 3397 75920c99ffc9
equal deleted inserted replaced
3373:78add3f69e39 3374:9a82918e063c
    37     buf_set,
    37     buf_set,
    38     buf_tosend
    38     buf_tosend
    39 } buf_state_t;
    39 } buf_state_t;
    40 
    40 
    41 static int global_write_dirty = 0;
    41 static int global_write_dirty = 0;
       
    42 static long hmitree_rlock = 0;
       
    43 static long hmitree_wlock = 0;
    42 
    44 
    43 typedef struct {
    45 typedef struct {
    44     void *ptr;
    46     void *ptr;
    45     __IEC_types_enum type;
    47     __IEC_types_enum type;
    46     uint32_t buf_index;
    48     uint32_t buf_index;
    47 
    49 
    48     /* publish/write/send */
    50     /* publish/write/send */
    49     long wlock;
       
    50     buf_state_t wstate[MAX_CONNECTIONS];
    51     buf_state_t wstate[MAX_CONNECTIONS];
    51 
    52 
    52     /* zero means not subscribed */
    53     /* zero means not subscribed */
    53     uint16_t refresh_period_ms[MAX_CONNECTIONS];
    54     uint16_t refresh_period_ms[MAX_CONNECTIONS];
    54     uint16_t age_ms[MAX_CONNECTIONS];
    55     uint16_t age_ms[MAX_CONNECTIONS];
    55 
    56 
    56     /* retrieve/read/recv */
    57     /* retrieve/read/recv */
    57     long rlock;
       
    58     buf_state_t rstate;
    58     buf_state_t rstate;
    59 
    59 
    60 } hmi_tree_item_t;
    60 } hmi_tree_item_t;
    61 
    61 
    62 static hmi_tree_item_t hmi_tree_item[] = {
    62 static hmi_tree_item_t hmi_tree_item[] = {
    81 
    81 
    82 %(var_access_code)s
    82 %(var_access_code)s
    83 
    83 
    84 static int write_iterator(uint32_t index, hmi_tree_item_t *dsc)
    84 static int write_iterator(uint32_t index, hmi_tree_item_t *dsc)
    85 {
    85 {
    86     uint32_t session_index = 0;
    86     {
    87     int value_changed = 0;
    87         uint32_t session_index = 0;
    88     if(AtomicCompareExchange(&dsc->wlock, 0, 1) == 0) {
    88         int value_changed = 0;
    89         void *dest_p = &wbuf[dsc->buf_index];
    89         void *dest_p = NULL;
    90         void *real_value_p = NULL;
    90         void *real_value_p = NULL;
    91         char flags = 0;
    91         void *visible_value_p = NULL;
    92         void *visible_value_p = UnpackVar(dsc, &real_value_p, &flags);
    92         USINT sz = 0;
    93         USINT sz = __get_type_enum_size(dsc->type);
       
    94         if(__Is_a_string(dsc)){
       
    95             sz = ((STRING*)visible_value_p)->len + 1;
       
    96         }
       
    97         while(session_index < MAX_CONNECTIONS) {
    93         while(session_index < MAX_CONNECTIONS) {
    98             if(dsc->wstate[session_index] == buf_set){
    94             if(dsc->wstate[session_index] == buf_set){
    99                 /* if being subscribed */
    95                 /* if being subscribed */
   100                 if(dsc->refresh_period_ms[session_index]){
    96                 if(dsc->refresh_period_ms[session_index]){
   101                     if(dsc->age_ms[session_index] + ticktime_ms < dsc->refresh_period_ms[session_index]){
    97                     if(dsc->age_ms[session_index] + ticktime_ms < dsc->refresh_period_ms[session_index]){
   105                         global_write_dirty = 1;
   101                         global_write_dirty = 1;
   106                     }
   102                     }
   107                 }
   103                 }
   108             }
   104             }
   109 
   105 
   110             if(dsc->wstate[session_index] == buf_new /* just subscribed 
   106             /* variable is sample only if just subscribed
   111                or already subscribed having value change */
   107                or already subscribed and having value change */
   112                || (dsc->refresh_period_ms[session_index] > 0 
   108             int do_sample = 0;
   113                    && (value_changed || (value_changed=memcmp(dest_p, visible_value_p, sz))) != 0)){
   109             int just_subscribed = dsc->wstate[session_index] == buf_new;
   114                 /* if not already marked/signaled, do it */
   110             if(!just_subscribed){
       
   111                 int already_subscribed = dsc->refresh_period_ms[session_index] > 0;
       
   112                 if(already_subscribed){
       
   113                     if(!value_changed){
       
   114                         if(!visible_value_p){
       
   115                             char flags = 0;
       
   116                             visible_value_p = UnpackVar(dsc, &real_value_p, &flags);
       
   117                             if(__Is_a_string(dsc)){
       
   118                                 sz = ((STRING*)visible_value_p)->len + 1;
       
   119                             } else {
       
   120                                 sz = __get_type_enum_size(dsc->type);
       
   121                             }
       
   122                             dest_p = &wbuf[dsc->buf_index];
       
   123                         }
       
   124                         value_changed = memcmp(dest_p, visible_value_p, sz) != 0;
       
   125                         do_sample = value_changed;
       
   126                     }else{
       
   127                         do_sample = 1;
       
   128                     }
       
   129                 }
       
   130             } else {
       
   131                 do_sample = 1;
       
   132             }
       
   133 
       
   134 
       
   135             if(do_sample){
   115                 if(dsc->wstate[session_index] != buf_set && dsc->wstate[session_index] != buf_tosend) {
   136                 if(dsc->wstate[session_index] != buf_set && dsc->wstate[session_index] != buf_tosend) {
   116                     if(dsc->wstate[session_index] == buf_new || ticktime_ms > dsc->refresh_period_ms[session_index]){
   137                     if(dsc->wstate[session_index] == buf_new \
       
   138                        || ticktime_ms > dsc->refresh_period_ms[session_index]){
   117                         dsc->wstate[session_index] = buf_tosend;
   139                         dsc->wstate[session_index] = buf_tosend;
   118                         global_write_dirty = 1;
   140                         global_write_dirty = 1;
   119                     } else {
   141                     } else {
   120                         dsc->wstate[session_index] = buf_set;
   142                         dsc->wstate[session_index] = buf_set;
   121                     }
   143                     }
   126             session_index++;
   148             session_index++;
   127         }
   149         }
   128         /* copy value if changed (and subscribed) */
   150         /* copy value if changed (and subscribed) */
   129         if(value_changed)
   151         if(value_changed)
   130             memcpy(dest_p, visible_value_p, sz);
   152             memcpy(dest_p, visible_value_p, sz);
   131         AtomicCompareExchange(&dsc->wlock, 1, 0);
       
   132     }
   153     }
   133     // else ... : PLC can't wait, variable will be updated next turn
   154     // else ... : PLC can't wait, variable will be updated next turn
   134     return 0;
   155     return 0;
   135 }
   156 }
   136 
   157 
   137 static uint32_t send_session_index;
   158 static uint32_t send_session_index;
   138 static int send_iterator(uint32_t index, hmi_tree_item_t *dsc)
   159 static int send_iterator(uint32_t index, hmi_tree_item_t *dsc)
   139 {
   160 {
   140     while(AtomicCompareExchange(&dsc->wlock, 0, 1))
       
   141         nRT_reschedule();
       
   142 
       
   143     if(dsc->wstate[send_session_index] == buf_tosend)
   161     if(dsc->wstate[send_session_index] == buf_tosend)
   144     {
   162     {
   145         uint32_t sz = __get_type_enum_size(dsc->type);
   163         uint32_t sz = __get_type_enum_size(dsc->type);
   146         if(sbufidx + sizeof(uint32_t) + sz <=  sizeof(sbuf))
   164         if(sbufidx + sizeof(uint32_t) + sz <=  sizeof(sbuf))
   147         {
   165         {
   157             sbufidx += sizeof(uint32_t) /* index */ + sz;
   175             sbufidx += sizeof(uint32_t) /* index */ + sz;
   158         }
   176         }
   159         else
   177         else
   160         {
   178         {
   161             printf("BUG!!! %%d + %%ld + %%d >  %%ld \n", sbufidx, sizeof(uint32_t), sz,  sizeof(sbuf));
   179             printf("BUG!!! %%d + %%ld + %%d >  %%ld \n", sbufidx, sizeof(uint32_t), sz,  sizeof(sbuf));
   162             AtomicCompareExchange(&dsc->wlock, 1, 0);
       
   163             return EOVERFLOW;
   180             return EOVERFLOW;
   164         }
   181         }
   165     }
   182     }
   166 
   183 
   167     AtomicCompareExchange(&dsc->wlock, 1, 0);
       
   168     return 0;
   184     return 0;
   169 }
   185 }
   170 
   186 
   171 static int read_iterator(uint32_t index, hmi_tree_item_t *dsc)
   187 static int read_iterator(uint32_t index, hmi_tree_item_t *dsc)
   172 {
   188 {
   173     if(AtomicCompareExchange(&dsc->rlock, 0, 1) == 0)
   189     if(dsc->rstate == buf_set)
   174     {
   190     {
   175         if(dsc->rstate == buf_set)
   191         void *src_p = &rbuf[dsc->buf_index];
   176         {
   192         void *real_value_p = NULL;
   177             void *src_p = &rbuf[dsc->buf_index];
   193         char flags = 0;
   178             void *real_value_p = NULL;
   194         void *visible_value_p = UnpackVar(dsc, &real_value_p, &flags);
   179             char flags = 0;
   195         memcpy(real_value_p, src_p, __get_type_enum_size(dsc->type));
   180             void *visible_value_p = UnpackVar(dsc, &real_value_p, &flags);
   196         dsc->rstate = buf_free;
   181             memcpy(real_value_p, src_p, __get_type_enum_size(dsc->type));
   197     }
   182             dsc->rstate = buf_free;
       
   183         }
       
   184         AtomicCompareExchange(&dsc->rlock, 1, 0);
       
   185     }
       
   186     // else ... : PLC can't wait, variable will be updated next turn
       
   187     return 0;
   198     return 0;
   188 }
   199 }
   189 
   200 
   190 void update_refresh_period(hmi_tree_item_t *dsc, uint32_t session_index, uint16_t refresh_period_ms)
   201 void update_refresh_period(hmi_tree_item_t *dsc, uint32_t session_index, uint16_t refresh_period_ms)
   191 {
   202 {
   192     while(AtomicCompareExchange(&dsc->wlock, 0, 1)) 
       
   193         nRT_reschedule();
       
   194 
       
   195     if(refresh_period_ms) {
   203     if(refresh_period_ms) {
   196         if(!dsc->refresh_period_ms[session_index])
   204         if(!dsc->refresh_period_ms[session_index])
   197         {
   205         {
   198             dsc->wstate[session_index] = buf_new;
   206             dsc->wstate[session_index] = buf_new;
   199         }
   207         }
   200     } else {
   208     } else {
   201         dsc->wstate[session_index] = buf_free;
   209         dsc->wstate[session_index] = buf_free;
   202     }
   210     }
   203     dsc->refresh_period_ms[session_index] = refresh_period_ms;
   211     dsc->refresh_period_ms[session_index] = refresh_period_ms;
   204     AtomicCompareExchange(&dsc->wlock, 1, 0);
       
   205 }
   212 }
   206 
   213 
   207 static uint32_t reset_session_index;
   214 static uint32_t reset_session_index;
   208 static int reset_iterator(uint32_t index, hmi_tree_item_t *dsc)
   215 static int reset_iterator(uint32_t index, hmi_tree_item_t *dsc)
   209 {
   216 {
   248     delete_RT_to_nRT_signal(svghmi_handle);
   255     delete_RT_to_nRT_signal(svghmi_handle);
   249 }
   256 }
   250 
   257 
   251 void __retrieve_svghmi()
   258 void __retrieve_svghmi()
   252 {
   259 {
   253     traverse_hmi_tree(read_iterator);
   260     if(AtomicCompareExchange(&hmitree_rlock, 0, 1) == 0) {
       
   261         traverse_hmi_tree(read_iterator);
       
   262         AtomicCompareExchange(&hmitree_rlock, 1, 0);
       
   263     }
   254 }
   264 }
   255 
   265 
   256 void __publish_svghmi()
   266 void __publish_svghmi()
   257 {
   267 {
   258     global_write_dirty = 0;
   268     global_write_dirty = 0;
   259     traverse_hmi_tree(write_iterator);
   269     if(AtomicCompareExchange(&hmitree_wlock, 0, 1) == 0) {
       
   270         traverse_hmi_tree(write_iterator);
       
   271         AtomicCompareExchange(&hmitree_wlock, 1, 0);
       
   272     }
   260     if(global_write_dirty) {
   273     if(global_write_dirty) {
   261         SVGHMI_WakeupFromRTThread();
   274         SVGHMI_WakeupFromRTThread();
   262     }
   275     }
   263 }
   276 }
   264 
   277 
   272 
   285 
   273     if(svghmi_continue_collect) {
   286     if(svghmi_continue_collect) {
   274         int res;
   287         int res;
   275         sbufidx = HMI_HASH_SIZE;
   288         sbufidx = HMI_HASH_SIZE;
   276         send_session_index = session_index;
   289         send_session_index = session_index;
       
   290 
       
   291         while(AtomicCompareExchange(&hmitree_wlock, 0, 1)){
       
   292             nRT_reschedule();
       
   293         }
       
   294 
   277         if((res = traverse_hmi_tree(send_iterator)) == 0)
   295         if((res = traverse_hmi_tree(send_iterator)) == 0)
   278         {
   296         {
   279             if(sbufidx > HMI_HASH_SIZE){
   297             if(sbufidx > HMI_HASH_SIZE){
   280                 memcpy(&sbuf[0], &hmi_hash[0], HMI_HASH_SIZE);
   298                 memcpy(&sbuf[0], &hmi_hash[0], HMI_HASH_SIZE);
   281                 *ptr = &sbuf[0];
   299                 *ptr = &sbuf[0];
   282                 *size = sbufidx;
   300                 *size = sbufidx;
       
   301                 AtomicCompareExchange(&hmitree_wlock, 1, 0);
   283                 return 0;
   302                 return 0;
   284             }
   303             }
       
   304             AtomicCompareExchange(&hmitree_wlock, 1, 0);
   285             return ENODATA;
   305             return ENODATA;
   286         }
   306         }
   287         // printf("collected BAD result %%d\n", res);
   307         // printf("collected BAD result %%d\n", res);
       
   308         AtomicCompareExchange(&hmitree_wlock, 1, 0);
   288         return res;
   309         return res;
   289     }
   310     }
   290     else
   311     else
   291     {
   312     {
   292         return EINTR;
   313         return EINTR;
   293     }
   314     }
   294 }
   315 }
   295 
   316 
   296 typedef enum {
   317 typedef enum {
       
   318     unset = -1,
   297     setval = 0,
   319     setval = 0,
   298     reset = 1,
   320     reset = 1,
   299     subscribe = 2
   321     subscribe = 2
   300 } cmd_from_JS;
   322 } cmd_from_JS;
   301 
   323 
   318     {
   340     {
   319         printf("svghmi_recv_dispatch MISMATCH !!\n");
   341         printf("svghmi_recv_dispatch MISMATCH !!\n");
   320         return -EINVAL;
   342         return -EINVAL;
   321     }
   343     }
   322 
   344 
       
   345     int ret;
       
   346     int got_wlock = 0;
       
   347     int got_rlock = 0;
       
   348     cmd_from_JS cmd_old = unset;
       
   349     cmd_from_JS cmd = unset;
       
   350 
   323     while(cursor < end)
   351     while(cursor < end)
   324     {
   352     {
   325         uint32_t progress;
   353         uint32_t progress;
   326         cmd_from_JS cmd = *(cursor++);
   354 
       
   355         cmd_old = cmd;
       
   356         cmd = *(cursor++);
       
   357 
       
   358         if(cmd_old != cmd){
       
   359             if(got_wlock){
       
   360                 AtomicCompareExchange(&hmitree_wlock, 1, 0);
       
   361                 got_wlock = 0;
       
   362             }
       
   363             if(got_rlock){
       
   364                 AtomicCompareExchange(&hmitree_rlock, 1, 0);
       
   365                 got_rlock = 0;
       
   366             }
       
   367         }
   327         switch(cmd)
   368         switch(cmd)
   328         {
   369         {
   329             case setval:
   370             case setval:
   330             {
   371             {
   331                 uint32_t index = *(uint32_t*)(cursor);
   372                 uint32_t index = *(uint32_t*)(cursor);
   348                     }
   389                     }
   349 
   390 
   350                     if((valptr + sz) <= end)
   391                     if((valptr + sz) <= end)
   351                     {
   392                     {
   352                         // rescheduling spinlock until free
   393                         // rescheduling spinlock until free
   353                         while(AtomicCompareExchange(&dsc->rlock, 0, 1)) 
   394                         if(!got_rlock){
   354                             nRT_reschedule();
   395                             while(AtomicCompareExchange(&hmitree_rlock, 0, 1)){
       
   396                                 nRT_reschedule();
       
   397                             }
       
   398                             got_rlock=1;
       
   399                         }
   355 
   400 
   356                         memcpy(dst_p, valptr, sz);
   401                         memcpy(dst_p, valptr, sz);
   357                         dsc->rstate = buf_set;
   402                         dsc->rstate = buf_set;
   358 
   403 
   359                         AtomicCompareExchange(&dsc->rlock, 1, 0);
       
   360                         progress = sz + sizeof(uint32_t) /* index */;
   404                         progress = sz + sizeof(uint32_t) /* index */;
   361                     }
   405                     }
   362                     else
   406                     else
   363                     {
   407                     {
   364                         return -EINVAL;
   408                         ret = -EINVAL;
       
   409                         goto exit_free;
   365                     }
   410                     }
   366                 }
   411                 }
   367                 else
   412                 else
   368                 {
   413                 {
   369                     return -EINVAL;
   414                     ret = -EINVAL;
       
   415                     goto exit_free;
   370                 }
   416                 }
   371             }
   417             }
   372             break;
   418             break;
   373 
   419 
   374             case reset:
   420             case reset:
   375             {
   421             {
   376                 progress = 0;
   422                 progress = 0;
   377                 reset_session_index = session_index;
   423                 reset_session_index = session_index;
       
   424                 if(!got_wlock){
       
   425                     while(AtomicCompareExchange(&hmitree_wlock, 0, 1)){
       
   426                         nRT_reschedule();
       
   427                     }
       
   428                     got_wlock = 1;
       
   429                 }
   378                 traverse_hmi_tree(reset_iterator);
   430                 traverse_hmi_tree(reset_iterator);
   379             }
   431             }
   380             break;
   432             break;
   381 
   433 
   382             case subscribe:
   434             case subscribe:
   384                 uint32_t index = *(uint32_t*)(cursor);
   436                 uint32_t index = *(uint32_t*)(cursor);
   385                 uint16_t refresh_period_ms = *(uint32_t*)(cursor + sizeof(uint32_t));
   437                 uint16_t refresh_period_ms = *(uint32_t*)(cursor + sizeof(uint32_t));
   386 
   438 
   387                 if(index < HMI_ITEM_COUNT)
   439                 if(index < HMI_ITEM_COUNT)
   388                 {
   440                 {
       
   441                     if(!got_wlock){
       
   442                         while(AtomicCompareExchange(&hmitree_wlock, 0, 1)){
       
   443                             nRT_reschedule();
       
   444                         }
       
   445                         got_wlock = 1;
       
   446                     }
   389                     hmi_tree_item_t *dsc = &hmi_tree_item[index];
   447                     hmi_tree_item_t *dsc = &hmi_tree_item[index];
   390                     update_refresh_period(dsc, session_index, refresh_period_ms);
   448                     update_refresh_period(dsc, session_index, refresh_period_ms);
   391                 }
   449                 }
   392                 else
   450                 else
   393                 {
   451                 {
   394                     return -EINVAL;
   452                     ret = -EINVAL;
       
   453                     goto exit_free;
   395                 }
   454                 }
   396 
   455 
   397                 progress = sizeof(uint32_t) /* index */ +
   456                 progress = sizeof(uint32_t) /* index */ +
   398                            sizeof(uint16_t) /* refresh period */;
   457                            sizeof(uint16_t) /* refresh period */;
   399             }
   458             }
   402                 printf("svghmi_recv_dispatch unknown %%d\n",cmd);
   461                 printf("svghmi_recv_dispatch unknown %%d\n",cmd);
   403 
   462 
   404         }
   463         }
   405         cursor += progress;
   464         cursor += progress;
   406     }
   465     }
   407     return was_hearbeat;
   466     ret = was_hearbeat;
   408 }
   467 
   409 
   468 exit_free:
       
   469     if(got_wlock){
       
   470         AtomicCompareExchange(&hmitree_wlock, 1, 0);
       
   471         got_wlock = 0;
       
   472     }
       
   473     if(got_rlock){
       
   474         AtomicCompareExchange(&hmitree_rlock, 1, 0);
       
   475         got_rlock = 0;
       
   476     }
       
   477     return ret;
       
   478 }
       
   479