⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ul_ufsm.c

📁 linux下的RS485的驱动 值得一看
💻 C
字号:
/*******************************************************************  uLan Communication - uL_DRV - multiplatform uLan driver  ul_ufsm.c	- finite state machine for building and receiving                  message frames on UART devices  (C) Copyright 1996-2004 by Pavel Pisa - project originator        http://cmp.felk.cvut.cz/~pisa  (C) Copyright 1996-2004 PiKRON Ltd.        http://www.pikron.com  (C) Copyright 2002-2004 Petr Smolik    The uLan driver project can be used and distributed   in compliance with any of next licenses   - GPL - GNU Public License     See file COPYING for details.   - LGPL - Lesser GNU Public License   - MPL - Mozilla Public License   - and other licenses added by project originator  Code can be modified and re-distributed under any combination  of the above listed licenses. If contributor does not agree with  some of the licenses, he/she can delete appropriate line.  WARNING: if you delete all lines, you are not allowed to  distribute code or sources in any form. *******************************************************************//*******************************************************************//* uLan main driver automata loop */ul_call_fnc uld_drvloop_proc_1, uld_drvloop_proc_2;ul_call_fnc uld_drvloop_rec_1, uld_drvloop_rec_2, uld_drvloop_rec_3, uld_drvloop_rec_4;int uld_drvloop(ul_drv *udrv, int ret_code){  if(((udrv->char_buff==(udrv->my_adr|0x100))||      (udrv->char_buff==0x100))&&     (udrv->char_buff==udrv->last_ctrl))  { /* it seems, that somebody wants us  */    udrv->con_flg=0;    udrv->xor_sum=udrv->char_buff+1;    UL_FCALL2(uld_recbeg_1,uld_drvloop_rec_1);    return UL_RC_PROC;  };  if(udrv->prep_bll.first!=NULL) /* we have something to proccess  */  {    LOG_CHIO(" call connect ");    UL_FCALL2(*udrv->fnc_connect,uld_drvloop_proc_1);    return UL_RC_PROC;  };  udrv->char_buff=0;  UL_FCALL(*udrv->fnc_recch);  return UL_RC_PROC;};int uld_drvloop_proc_error(ul_drv *udrv){ ul_mem_blk *mes;  udrv->fnc_timeout=NULL;  LOG_MESSAGES("uLan : send message ERROR\n");  if((mes=udrv->con_message)!=NULL)  {udrv->con_message=NULL;   if((UL_BLK_HEAD(mes).flg&UL_BFL_NORE)||      (++UL_BLK_HEAD(mes).retry_cnt>=UL_RETRY_CNT))   { UL_BLK_HEAD(mes).flg|=UL_BFL_FAIL;     ul_bll_move_mes(&udrv->proc_bll,mes);     LOG_FAILS(KERN_ERR "uLan : send message (d:%d,s:%d,c:%X,f:%X,l:%d) FAILED after %d attempts\n",                   UL_BLK_HEAD(mes).dadr,UL_BLK_HEAD(mes).sadr,                   UL_BLK_HEAD(mes).cmd,UL_BLK_HEAD(mes).flg,                   UL_BLK_HEAD(mes).len,UL_BLK_HEAD(mes).retry_cnt);     SCHEDULE_BH(udrv);   }else if(UL_BLK_HEAD(mes).flg&UL_BFL_REWA)     ul_bll_move_mes(&udrv->prep_bll,mes);  };  udrv->char_buff=0x1FF;   return 0;};int uld_drvloop_proc_1(ul_drv *udrv, int ret_code){  if(ret_code<0) {UL_FNEXT(uld_drvloop); return UL_RC_PROC;};  LOG_MESSAGES("uLan : begin of send message\n");  udrv->fnc_timeout=&uld_drvloop_proc_error;  udrv->con_message=udrv->prep_bll.first;  UL_FCALL2(uld_prmess,uld_drvloop_proc_2);  return UL_RC_PROC;};int uld_drvloop_proc_2(ul_drv *udrv, int ret_code){  ul_mem_blk *mes;  udrv->fnc_timeout=NULL;  udrv->char_buff=udrv->my_adr|0x180;   UL_FCALL2(*udrv->fnc_sndch,uld_drvloop);  if(udrv->con_message==NULL) return UL_RC_PROC;  if(ret_code<0)  {uld_drvloop_proc_error(udrv);  }else{    LOG_MESSAGES("uLan : send message finished OK\n");    mes=udrv->con_message;    udrv->con_message=NULL;    if(UL_BLK_HEAD(mes).flg&UL_BFL_M2IN ||        UL_BLK_HEAD(mes).dadr==udrv->my_adr)    {      ul_bll_move_mes(&udrv->proc_bll,mes);      SCHEDULE_BH(udrv);    } else     ul_bll_free_mes(mes);  };  return UL_RC_PROC;};int uld_drvloop_rec_error(ul_drv *udrv){ ul_mem_blk *mes;  udrv->fnc_timeout=NULL;  LOG_MESSAGES("uLan : receive message ERROR\n");  if((mes=udrv->con_message)!=NULL)  { udrv->con_message=NULL;    ul_bll_free_mes(mes);  };  udrv->char_buff=0x1FF;  return 0;};int uld_drvloop_rec_1(ul_drv *udrv, int ret_code){ ul_mem_blk *mes;  if(ret_code<0) {UL_FNEXT(uld_drvloop); return UL_RC_PROC;};  LOG_MESSAGES("uLan : begin of receive message\n");  mes=ul_new_frame_head(udrv,udrv->con_dadr,udrv->con_sadr,                 	udrv->con_cmd,0);  if(mes==NULL)   { LOG_FAILS(KERN_ERR "uLan : NO memory for receive\n");    UL_FNEXT(uld_drvloop); return UL_RC_PROC;  };  ul_bll_ins(&udrv->work_bll,mes);  udrv->con_message=mes;  udrv->fnc_timeout=&uld_drvloop_rec_error;  udrv->con_frame=mes;  UL_FCALL2(uld_recdata,uld_drvloop_rec_2);  return UL_RC_PROC;};int uld_drvloop_rec_2(ul_drv *udrv, int ret_code){  if(ret_code<0)   { uld_drvloop_rec_error(udrv);    UL_FNEXT(uld_drvloop); return UL_RC_PROC;  };  #ifdef UL_WITH_IAC    UL_FCALL2(uld_recend,uld_drvloop_rec_3);  #else     UL_FCALL2(uld_recend,uld_drvloop_rec_4);  #endif /* UL_WITH_IAC  */  return UL_RC_PROC;};#ifdef UL_WITH_IACint uld_drvloop_rec_3(ul_drv *udrv, int ret_code){   if(ret_code<0)   { uld_drvloop_rec_error(udrv);    UL_FNEXT(uld_drvloop); return UL_RC_PROC;  };  UL_FCALL2(uld_prmess_iac,uld_drvloop_rec_4);  return UL_RC_PROC; }#endif /* UL_WITH_IAC  */int uld_drvloop_rec_4(ul_drv *udrv, int ret_code){ ul_mem_blk *mes;  if(ret_code<0)   { uld_drvloop_rec_error(udrv);    UL_FNEXT(uld_drvloop); return UL_RC_PROC;  };  mes=udrv->con_message;  udrv->fnc_timeout=NULL;  udrv->con_message=NULL;  if (ret_code==UL_RC_FREEMSG) {    ul_bll_free_mes(mes);    UL_FNEXT(uld_drvloop);    LOG_MESSAGES("uLan : receive message was freed\n");    return UL_RC_PROC;  }  UL_BLK_HEAD(mes).stamp=ul_gen_stamp();  ul_bll_move_mes(&udrv->proc_bll,mes);  SCHEDULE_BH(udrv);  UL_FNEXT(uld_drvloop);  LOG_MESSAGES("uLan : end of receive message\n");  return UL_RC_PROC;};int ul_max_cycle_cnt=0;int ul_max_cycle_time=0;int ul_irq_seq_num=0;#ifdef ENABLE_UL_IRQ_STALE_WDG	int ul_irq_stale_wdg_cnt=0;#endif /* ENABLE_UL_IRQ_STALE_WDG *//*** Interrupt entry point ***/ul_irqreturn_t uld_irq_handler(UL_IRQ_HANDLER_ARGS(intno, dev_id)){  #ifdef UL_GLOBAL_IRQ_LOCK_FINI   UL_GLOBAL_IRQ_LOCK_FINI  #endif  int irq_loop_cnt=0;  int cycle_cnt=0;  int cycle_time;  int ret_code;  #ifdef UL_LOG_ENABLE    int seq_num=++ul_irq_seq_num;  #endif  ul_drv* udrv=(ul_drv*)dev_id;  if(udrv->magic!=UL_DRV_MAGIC)  {    #ifdef FOR_LINUX_KERNEL     panic("uld_irq_handler : BAD udrv magic !!!");    #elif defined(_WIN32)     UL_PRINTF("uld_irq_handler : BAD udrv magic !!!\n");     return FALSE;    #elif defined(__DJGPP__)||defined(CONFIG_OC_UL_DRV_SYSLESS)     UL_PRINTF("uld_irq_handler : BAD udrv magic !!!\n");     return;    #else     error("uld_irq_handler : BAD udrv magic !!!");    #endif  }  #ifdef UL_GLOBAL_IRQ_LOCK   UL_GLOBAL_IRQ_LOCK;  #endif  if(uld_test_dfl(udrv,CHIPOK))  do  {     #ifdef ENABLE_UL_IRQ_STALE_WDG	    /* last rescue code for stale IRQ !!!!!! */    if(ul_irq_stale_wdg_cnt++>10000)    {      SCHEDULE_BH(udrv); /* Test activation of BH */      if(ul_irq_stale_wdg_cnt>20000)      {	LOG_FATAL(KERN_CRIT "Stale IRQ uLan IRQ signal !!!\n");	udrv->fnc_cctrl(udrv,UL_CC_GENIRQ,0);	if(ul_irq_stale_wdg_cnt<25000) break;	#ifdef FOR_LINUX_KERNEL	 LOG_FATAL(KERN_CRIT "Disabling IRQ %d forever !!!\n",intno);	 disable_irq_nosync(intno);	#endif	break;      }    }     #endif /* ENABLE_UL_IRQ_STALE_WDG */    do /* IRQ fully SMP and re-entrant processing */    {      uld_set_dfl(udrv,ASK_ISR);      if(uld_test_and_set_dfl(udrv,IN_ISR))      { LOG_IRQ("uLan IRQ %d arrived, but else is in ISR\n",intno);        break;      };      /* only one CPU in no nested levels at time */      uld_clear_dfl(udrv,ASK_ISR);      while((ret_code=udrv->fnc_pool(udrv))!=0)      {	LOG_SEQNUM("\n<<< seq %d ",seq_num);	LOG_IRQ("uLan IRQ %d arrived, code = %d\n",intno,ret_code);	cycle_time=RDTSC;	while((ret_code=udrv->fnc_act(udrv,ret_code))!=0) 	  if(cycle_cnt++>100) 	    {LOG_FATAL(KERN_CRIT "Infinite loop in uLan IRQ handler !!!\n");break;};	cycle_time=RDTSC-cycle_time;	if(cycle_cnt>ul_max_cycle_cnt) ul_max_cycle_cnt=cycle_cnt;	if(cycle_time>ul_max_cycle_time) ul_max_cycle_time=cycle_time;	LOG_SEQNUM(" seq %d >>>",seq_num);	if(irq_loop_cnt++>10)	{ LOG_FATAL(KERN_CRIT "Stale IRQ - uLan state handlers !!!\n");	  udrv->fnc_cctrl(udrv,UL_CC_GENIRQ,0);	  break;	};	uld_atomic_clear_dfl(udrv,NACTIV);      };      uld_atomic_clear_dfl(udrv,IN_ISR);    }    while(uld_atomic_test_dfl(udrv,ASK_ISR));  }while(0);  #ifdef UL_GLOBAL_IRQ_UNLOCK   UL_GLOBAL_IRQ_UNLOCK;  #endif   return UL_IRQ_RETVAL(irq_loop_cnt);};/*** Timeout entry point ***/void uld_timeout(ul_drv *udrv){  #ifdef UL_GLOBAL_IRQ_LOCK_FINI   UL_GLOBAL_IRQ_LOCK_FINI  #endif  #if defined(_WIN32)&&defined(UL_WITH_PCI)   KIRQL old_irql;  #endif  int cycle_cnt=0;  int cycle_time;  int ret_code=0;  #ifdef UL_GLOBAL_IRQ_LOCK   UL_GLOBAL_IRQ_LOCK;  #endif  LOG_IRQ("uLan timeout activated\n");  if(uld_test_dfl(udrv,CHIPOK))  {    #ifdef FOR_LINUX_KERNEL    if(udrv->irq) disable_irq_nosync(udrv->irq);    #elif defined(_WIN32)&&defined(UL_WITH_PCI)    KeRaiseIrql(uL_SpinLock_Irql,&old_irql);    #endif    do    {      if(uld_test_and_set_dfl(udrv,IN_ISR))      { LOG_IRQ("uLan timeout, but else is in ISR\n");        break;      };      /* only one CPU with no nested levels goes there */      uld_clear_dfl(udrv,ASK_ISR);      if((ret_code=udrv->fnc_pool(udrv))==0)      {/* if first pass check for timeout conditions */	if(!cycle_cnt&&(uld_atomic_test_dfl(udrv,NACTIV)||            (udrv->last_ctrl&0x80)))	{ cycle_cnt++;	  uld_clear_dfl(udrv,WDFORCED);	  if(udrv->fnc_timeout) ret_code=udrv->fnc_timeout(udrv);	  if(ret_code==0)	  {udrv->fnc_sp=&udrv->fnc_stack[0];	   udrv->fnc_act=&uld_drvloop;	   ret_code=UL_RC_ACTIVATE;	  };	};      };      cycle_time=RDTSC;      while(ret_code)      { ret_code=udrv->fnc_act(udrv,ret_code);        if(cycle_cnt++>100) 	  {LOG_FATAL(KERN_CRIT "Infinite loop in uLan Timeout handler !!!\n");break;};      };      cycle_time=RDTSC-cycle_time;      if(cycle_cnt>ul_max_cycle_cnt) ul_max_cycle_cnt=cycle_cnt;      if(cycle_time>ul_max_cycle_time) ul_max_cycle_time=cycle_time;      uld_clear_dfl(udrv,NACTIV);      uld_atomic_clear_dfl(udrv,IN_ISR);    }    while(uld_atomic_test_dfl(udrv,ASK_ISR));    #ifdef FOR_LINUX_KERNEL     if(udrv->irq) enable_irq(udrv->irq);    #elif defined(_WIN32)&&defined(UL_WITH_PCI)     KeLowerIrql(old_irql);    #endif  };  #ifdef UL_GLOBAL_IRQ_UNLOCK   UL_GLOBAL_IRQ_UNLOCK;  #endif};/* link watchdog timer function */#ifdef _WIN32VOID  ulan_wd_dpc(IN PKDPC Dpc,IN PVOID data,		  IN PVOID arg1,IN PVOID arg2)#else /* _WIN32 */ void ulan_do_wd_timer(unsigned long data)#endif /* _WIN32 */{  ul_drv* udrv=(ul_drv*)data;  if(udrv->magic!=UL_DRV_MAGIC)  {    #ifdef FOR_LINUX_KERNEL     panic("ulan_do_wd_timer : BAD udrv magic !!!");    #elif defined(_WIN32)||defined(__DJGPP__)||defined(CONFIG_OC_UL_DRV_SYSLESS)     UL_PRINTF("ulan_do_wd_timer : BAD udrv magic !!!\n");     return;    #else     error("ulan_do_wd_timer : BAD udrv magic !!!");    #endif  }  if(!uld_test_dfl(udrv,CHIPOK)) return;  if((udrv->prep_bll.first!=NULL)||uld_test_dfl(udrv,WDFORCED))  {    if(uld_test_and_set_dfl(udrv,NACTIV)||      (udrv->last_ctrl&0x80)) uld_timeout(udrv);    #ifndef _WIN32       SCHEDULE_UDRV_WDTIM(udrv,jiffies+ULD_HZ/25+1);    #else /* _WIN32 */     { LARGE_INTEGER delay;       delay=RtlConvertLongToLargeInteger(-40*10000);       KeSetTimer(&udrv->wd_timer,delay,&udrv->wd_timer_dpc);     }    #endif /* _WIN32 */  };};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -