| 
									
										
										
										
											2023-06-10 11:52:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "signal.h"
 | 
					
						
							|  |  |  | #include "board.h"
 | 
					
						
							|  |  |  | #include "stdlib.h"
 | 
					
						
							|  |  |  | #include "stdio.h"
 | 
					
						
							|  |  |  | #include "debug.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct{ | 
					
						
							|  |  |  |   void *mutex; | 
					
						
							|  |  |  |   signal_list *head; | 
					
						
							|  |  |  | }self_def; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static self_def g_self; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int signal_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   self_def *s=&g_self; | 
					
						
							|  |  |  |   if(s->mutex==0) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     s->mutex=rt_mutex_create("signal_",RT_IPC_FLAG_FIFO); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void cpy4byte(uint32_t *dst,uint32_t *src,int num_4byte) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   for(int i=0;i<num_4byte;i++) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     dst[i]=src[i]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SLOT_FUN_RUN(fun,param) \
 | 
					
						
							|  |  |  |   ((slot_fun_def)(fun))(param[0],param[1],param[2],\ | 
					
						
							|  |  |  |     param[3],param[4],param[5],param[6],param[7]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef void (*slot_fun_def)(uint32_t a,uint32_t b,uint32_t c,uint32_t d,uint32_t e,uint32_t f,uint32_t g,uint32_t h); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void slot_run(void *t) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   param_check(t); | 
					
						
							|  |  |  |   slot_run_def *s=t; | 
					
						
							|  |  |  |   int msg_size=sizeof(slot_msg_def)+sizeof(uint32_t)*8; | 
					
						
							|  |  |  |   slot_msg_def *msg=calloc(1,msg_size); | 
					
						
							|  |  |  |   while(s->run) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     rt_mq_recv(s->mb,msg,msg_size,RT_WAITING_FOREVER); | 
					
						
							|  |  |  |     SLOT_FUN_RUN(msg->fun,msg->param); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   free(msg); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 创建一个线程
 | 
					
						
							|  |  |  | sig_thread thread_creat(int pro) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   static uint16_t count=0; | 
					
						
							|  |  |  |   char name[20]={0}; | 
					
						
							|  |  |  |   slot_run_def *run=calloc(1,sizeof(slot_run_def)); | 
					
						
							|  |  |  |   run->run=1; | 
					
						
							|  |  |  |   sprintf(name,"sig_mq#%d",count); | 
					
						
							| 
									
										
										
										
											2023-09-09 17:27:06 +08:00
										 |  |  |   run->mb=rt_mq_create(name,(sizeof(slot_msg_def)+sizeof(uint32_t)*8),30,RT_IPC_FLAG_FIFO); | 
					
						
							| 
									
										
										
										
											2023-06-10 11:52:00 +08:00
										 |  |  |   sprintf(name,"sig_t#%d",count); | 
					
						
							| 
									
										
										
										
											2023-09-09 17:27:06 +08:00
										 |  |  |   rt_thread_t rt_t=rt_thread_create(name,slot_run,run,1024,pro,20); | 
					
						
							| 
									
										
										
										
											2023-06-10 11:52:00 +08:00
										 |  |  |   rt_thread_startup(rt_t); | 
					
						
							|  |  |  |   count++; | 
					
						
							|  |  |  |   return run->mb; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void thread_delete(sig_thread t) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   // 删除线程需要删除与此线程相关的所有信号槽
 | 
					
						
							|  |  |  |   // 删除消息队列
 | 
					
						
							|  |  |  |   param_check(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 如果这个类的信号已注册
 | 
					
						
							|  |  |  | static signal_list *find(void *sig_obj,void *signal_) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   self_def *s=&g_self; | 
					
						
							|  |  |  |   signal_list *l=s->head; | 
					
						
							|  |  |  |   while(l!=0) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if(l->signal_==signal_&&l->sig_obj==sig_obj) | 
					
						
							|  |  |  |       return l; | 
					
						
							|  |  |  |     l=l->next; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int connect(void *sig_obj,void *signal_,sig_thread t,void *slot_obj,void *slot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   self_def *s=&g_self; | 
					
						
							|  |  |  |   signal_def *sig; | 
					
						
							|  |  |  |   sig=signal_find(signal_); | 
					
						
							|  |  |  |   if(sig==0) return -1; | 
					
						
							|  |  |  |   rt_mutex_take(s->mutex,RT_WAITING_FOREVER); | 
					
						
							|  |  |  |   slot_list *slo=calloc(1,sizeof(slot_list)); | 
					
						
							|  |  |  |   param_check(slo); | 
					
						
							|  |  |  |   slo->fun=slot; | 
					
						
							|  |  |  |   slo->mb=t; | 
					
						
							|  |  |  |   slo->next=0; | 
					
						
							|  |  |  |   slo->obj=slot_obj; | 
					
						
							|  |  |  |   signal_list *sig_l=find(sig_obj,signal_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if(sig_l==0){ | 
					
						
							|  |  |  |     sig_l=calloc(1,sizeof(signal_list)); | 
					
						
							|  |  |  |     param_check(sig_l); | 
					
						
							|  |  |  |     sig_l->signal_=signal_; | 
					
						
							|  |  |  |     sig_l->sig_obj=sig_obj; | 
					
						
							|  |  |  |     sig_l->next=s->head; | 
					
						
							|  |  |  |     s->head=sig_l; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   slo->next=sig_l->head; | 
					
						
							|  |  |  |   sig_l->head=slo; | 
					
						
							|  |  |  |   //DBG_LOG("signal connect:%08x",slo);
 | 
					
						
							|  |  |  |   rt_mutex_release(s->mutex); | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int disconnect(void *sig_obj,void *signal_,sig_thread t,void *slot_obj,void *slot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   self_def *s=&g_self; | 
					
						
							|  |  |  |   signal_list *sig; | 
					
						
							|  |  |  |   sig=find(sig_obj,signal_); | 
					
						
							|  |  |  |   if(sig==0) return -1; | 
					
						
							|  |  |  |   int ret=-1; | 
					
						
							|  |  |  |   rt_mutex_take(s->mutex,RT_WAITING_FOREVER); | 
					
						
							|  |  |  |   slot_list *next=sig->head; | 
					
						
							|  |  |  |   slot_list *prev=0; | 
					
						
							|  |  |  |   while(next!=0) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if(next->fun==slot&&next->obj==slot_obj) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if(prev) prev->next=next->next; | 
					
						
							|  |  |  |       else sig->head=next->next; | 
					
						
							|  |  |  |       //DBG_LOG("signal disconnect:%08x",next);
 | 
					
						
							|  |  |  |       free(next); | 
					
						
							|  |  |  |       ret=0; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     prev=next; | 
					
						
							|  |  |  |     next=next->next; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   rt_mutex_release(s->mutex); | 
					
						
							|  |  |  |   return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 消除与指定对象相关的所有信号槽连接
 | 
					
						
							|  |  |  | int disconnect_sig(void *sig_obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   self_def *s=&g_self; | 
					
						
							|  |  |  |   rt_mutex_take(s->mutex,RT_WAITING_FOREVER); | 
					
						
							|  |  |  |   signal_list *sig=s->head; | 
					
						
							|  |  |  |   signal_list *prev_sig=0; | 
					
						
							|  |  |  |   while(sig!=0) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if(sig->sig_obj==sig_obj) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       slot_list *next=sig->head; | 
					
						
							|  |  |  |       while(next!=0) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         sig->head=next->next; | 
					
						
							|  |  |  |         free(next); | 
					
						
							|  |  |  |         next=sig->head; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if(prev_sig) prev_sig=sig->next; | 
					
						
							|  |  |  |       else s->head=sig->next; | 
					
						
							|  |  |  |       free(sig); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     prev_sig=sig; | 
					
						
							|  |  |  |     sig=sig->next; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   rt_mutex_release(s->mutex); | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 消除与指定对象相关的所有信号槽连接
 | 
					
						
							|  |  |  | int disconnect_slot(void *slot_obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   self_def *s=&g_self; | 
					
						
							|  |  |  |   rt_mutex_take(s->mutex,RT_WAITING_FOREVER); | 
					
						
							|  |  |  |   signal_list *sig=s->head; | 
					
						
							|  |  |  |   while(sig!=0) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     slot_list *next=sig->head; | 
					
						
							|  |  |  |     slot_list *prev=0; | 
					
						
							|  |  |  |     while(next!=0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if(next->obj==slot_obj) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         if(prev) prev->next=next->next; | 
					
						
							|  |  |  |         else sig->head=next->next; | 
					
						
							|  |  |  |         free(next); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       prev=next; | 
					
						
							|  |  |  |       next=next->next; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     sig=sig->next; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   rt_mutex_release(s->mutex); | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | signal_def *signal_find(void *signal_) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   extern const int signalstruct$$Base; | 
					
						
							|  |  |  |   extern const int signalstruct$$Limit; | 
					
						
							|  |  |  |   signal_def *start=(signal_def *)&signalstruct$$Base; | 
					
						
							|  |  |  |   signal_def *end=(signal_def *)&signalstruct$$Limit; | 
					
						
							|  |  |  |   for(signal_def *t=start;t<end;t++) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if(t->signal_==signal_) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       return t; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 发送信号
 | 
					
						
							|  |  |  | int _signal_emit(void *sig_obj,void *signal_,uint32_t *param,int param_num) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   self_def *s=&g_self; | 
					
						
							|  |  |  |   signal_list *sig=find(sig_obj,signal_); | 
					
						
							|  |  |  |   if(sig==0) return -1; | 
					
						
							|  |  |  |   if(param_num>7) return -2; | 
					
						
							|  |  |  |   int size=sizeof(slot_msg_def)+sizeof(uint32_t)*(8); | 
					
						
							|  |  |  |   slot_msg_def *m=malloc(size); | 
					
						
							|  |  |  |   rt_mutex_take(s->mutex,RT_WAITING_FOREVER); | 
					
						
							|  |  |  |   slot_list *h=sig->head; | 
					
						
							|  |  |  |   m->param_num=param_num; | 
					
						
							|  |  |  |   m->src=signal_; | 
					
						
							|  |  |  |   while(h) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m->fun=h->fun; | 
					
						
							|  |  |  |     if(h->obj) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       cpy4byte(m->param+1,param,param_num); | 
					
						
							|  |  |  |       m->param[0]=(uint32_t)h->obj; | 
					
						
							|  |  |  |     }else{ | 
					
						
							|  |  |  |       cpy4byte(m->param,param,param_num); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if(h->mb){ | 
					
						
							|  |  |  |       rt_mq_send(h->mb,m,size); | 
					
						
							|  |  |  |     }else{ | 
					
						
							|  |  |  |       SLOT_FUN_RUN(m->fun,m->param); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     h=h->next; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   rt_mutex_release(s->mutex); | 
					
						
							|  |  |  |   free(m); | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 |