/*********************************************************************** * @file name: candrvctrl.c * @create date: 2022-11-19 * @author * @version: V 1.0.0 * @remark: 这个模块对can外设进行统一管理,忽略MCU接口的不同,对外一个统一的接口 MCU的更换不涉及到这里 ************************************************************************/ /********************************************************************************************************************* //CANDRVCTRL 作为传输协议与can驱动之间的中间层,作为一个纽带来将两者进行连接 // ////////////////////////////////////////////////////////////////////////////////////////////////////// // CAN驱动<------> 驱动管理层 ////////////////////////////////////////////////////////////////////////////////////////////////////// //can通道id和can消息帧id两者之间的同事用canid来表示容易出现混淆, // 故用chan表示can通道 // 用frmid表示can消息帧id // // //can驱动层将需要给传输层控制的接口通过st_cancb * RegisterCanIF(st_canif *if) 接口传给此模块 //st_cancb * RegisterCanIF(st_canif *if) 驱动层将某接口的控制权交给CanDrvCtrl模块 //参数st_canif 是驱动统一交给CanDrvCtrl 的接口列表,其中ConfigCan ,canSend和canid必须提供 //返回回调函数,驱动必须在适当的时候对其进行调用 *********************************************************************************************************************/ #include "porting.h" #include "candrvctrl.h" #if 0 #define M_DEBUGF printf #else #define M_DEBUGF(...) ; #endif #define MAX_CAN_IF_NUM 2 #define PROTOCOL_VALID(PL) (PL.prompt[0] !=0) //判断是否有协议安装在某个接口,通过协议名字来进行 #define SET_PROTOCOL_INVALID(PL) (PL.prompt[0] =0) typedef enum { e_step_send_idle=0, //空闲等待发送条件到达,进入e_step_send,通过定时器操作 e_step_send, //进行发送然后进入e_step_waitack等待, //通过消息触发 e_step_waitack, //通过定时器 e_step_resend, //进行重发,当超时或等应答过程出现异常的时候 e_step_fail, //已经发送失败 e_step_suc, //发送成功 }st_sendstep; typedef struct { unsigned int frmid; //can信息id unsigned char sendindex; unsigned char datalen; unsigned char data[8]; unsigned int msgident; void(*cb)(unsigned int msgident,unsigned int result); }st_senditem; typedef struct { unsigned int frmid; //can信息id unsigned char datalen; unsigned char data[8]; }st_recitem; typedef struct { unsigned char stimes; st_sendstep step; st_senditem sending; //当前正在发送的数据 unsigned char waittime; //等待的时间 unsigned char retrytimes; }st_sendmsg; typedef struct { st_canif canif; st_pl pl; unsigned char linkSts; st_fifo_t rec; st_fifo_t send; unsigned char *prec; unsigned char *psend; st_sendmsg smsg; //当前发送消息 }st_if; static void hdlIfSendSuccessCb(unsigned char chan,unsigned int index); static void hdlIfBusErrorCb(unsigned char chan,bool sending); static void hdlIfBusErrorStsCb(unsigned char chan,bool sending); static bool hdlIfFrmReceve(unsigned char chan,unsigned int canid,const unsigned char *data,unsigned char len); static void HdlSendMsgSuccess(st_if* pif,unsigned char index); static void hdlIfBusOffCb(unsigned char chan); static st_if CanIF[MAX_CAN_IF_NUM]; static st_cancb canifcb ={ hdlIfSendSuccessCb, hdlIfBusErrorCb, hdlIfBusErrorStsCb, hdlIfBusOffCb, hdlIfFrmReceve}; static st_if* GetIfFromChanel(unsigned char chan) { unsigned char i; for(i=0;(ilinkSts <= e_sts_closed) { if(pif->canif.canClose != NULL) pif->canif.canClose(chan); } else if(pif->linkSts == e_err_sending && sending) { M_DEBUGF("[CDCtrl]hdlIfBusErrorStsCb: 检测到总线发送异常!\n"); pif->linkSts = e_err_sending; can_kill( E_CAN_MSG_SIG,e_err_sending,chan); } else if(pif->linkSts != e_err_sending && sending == false) { M_DEBUGF("[CDCtrl]hdlIfBusErrorStsCb: 检测到总线接收异常!\n"); pif->linkSts = e_err_receive; can_kill( E_CAN_MSG_SIG,e_err_receive,chan); } else { /* 其他情况忽略 */ } } } static void hdlIfBusErrorStsCb(unsigned char chan,bool sending) { hdlIfBusErrorCb(chan,sending); } static void hdlIfBusOffCb(unsigned char chan) { st_if* pif; pif=GetIfFromChanel(chan); if(pif != NULL) { if(pif->linkSts <= e_sts_closed) { if(pif->canif.canClose != NULL) pif->canif.canClose(chan); } else { M_DEBUGF("[CDCtrl]hdlIfBusOffCb: 检测到总线BUSOFF!\n"); pif->linkSts = e_err_bussoff; can_kill( E_CAN_MSG_SIG,e_err_bussoff,chan); } } } static st_recitem tmpRItem; static bool hdlIfFrmReceve(unsigned char chan,unsigned int canid,const unsigned char *data,unsigned char len) { st_if* pif; pif = GetIfFromChanel(chan); if(pif != NULL && pif->linkSts >= e_sts_working) { if(e_err_receive == pif->linkSts) { pif->linkSts=e_sts_working; } if(pif->pl.flg&CAN_FLG_SYNCRECEIVE) { if(pif->pl.hdlRecCanMsg!=NULL) pif->pl.hdlRecCanMsg(canid,data,len); } else { tmpRItem.frmid = canid; tmpRItem.datalen = len; if(tmpRItem.datalen > 0 && tmpRItem.datalen<=8) CAN_COPY(tmpRItem.data,data,tmpRItem.datalen); sfifo_write(&pif->rec,&tmpRItem); if(sfifo_full(&pif->rec)) { M_DEBUGF("[CDCtrl]hdlIfFrmReceve: 接收缓冲已满\n"); pif->linkSts=e_err_overfllow; can_kill( E_CAN_MSG_SIG,e_err_overfllow,chan); } } } return true; } //注册通信接口和初始化 st_cancb * RegisterCanIF(const st_canif *IF) { unsigned char i; if(IF == NULL || IF->ConfigCan == NULL || IF->canSend==NULL ) return NULL; for(i=0;ichan) return NULL; } for(i=0;i= WAIT_ACK_TIME) { CanIF[i].smsg.step = e_step_resend; can_kill( E_CAN_MSG_SIG,e_sts_needsend,CanIF[i].canif.chan); } } } } static void StartResendMsgTmr(void) { if(waitSendAck == 0) waitSendAck = can_timer_create(waitSendMsgAck); if(can_timer_switch(waitSendAck) == false) can_timer_start(waitSendAck, WAIT_ACK_INTERVAL); } static void HdlAllSengMsgSts(st_if* pif) { bool flg = false; #if CAN_SEND_FASET_MODE > 0 do { flg = false; #endif switch(pif->smsg.step) { case e_step_send_idle: //空闲等待发送条件到达,进入e_step_send,通过定时器操作 if(pif->linkSts >= e_sts_working) { if(sfifo_empty(&(pif->send))==false) { if(sfifo_read(&(pif->send),&(pif->smsg.sending))) { pif->smsg.step=e_step_send; pif->smsg.stimes = 0; pif->smsg.waittime = 0; } flg = true; } } break; case e_step_send: //进行发送然后进入e_step_waitack等待, //通过消息触发 pif->smsg.sending.sendindex = pif->canif.canSend(pif->canif.chan,pif->smsg.sending.frmid,pif->smsg.sending.data,pif->smsg.sending.datalen); pif->smsg.stimes++; if(pif->smsg.sending.sendindex != 0xFF) { pif->smsg.step=e_step_waitack; pif->smsg.waittime = 0; flg = true; if(pif->linkSts == e_err_sending) pif->linkSts = e_sts_working; } else { if(pif->smsg.stimes >= pif->pl.resendTimes) { pif->smsg.step=e_step_fail; flg = true; } } break; #if 1 case e_step_waitack: //通过定时器 break; case e_step_resend: //进行重发,当超时或等应答过程出现异常的时候 if(pif->smsg.stimes >= pif->pl.resendTimes) { pif->smsg.step=e_step_fail; } else { pif->smsg.step=e_step_send; } flg = true; break; case e_step_fail: //已经发送失败 pif->smsg.step=e_step_send_idle; if(pif->smsg.sending.cb != NULL) {pif->smsg.sending.cb(pif->smsg.sending.msgident,_FAILURE);} else if (pif->pl.hdlCommSent != NULL) {pif->pl.hdlCommSent(pif->smsg.sending.msgident,_FAILURE);} flg = true; break; case e_step_suc: //发送成功 pif->smsg.step=e_step_send_idle; #if CAN_SEND_FASET_MODE > 0 if(pif->smsg.sending.cb != NULL) {can_kill(E_CAN_MSG_CB_SIG, (unsigned int)(pif->smsg.sending.cb),pif->smsg.sending.msgident);} else if (pif->pl.hdlCommSent != NULL) {can_kill(E_CAN_MSG_CB_SIG, (unsigned int)(pif->pl.hdlCommSent),pif->smsg.sending.msgident);} #else if(pif->smsg.sending.cb != NULL) {pif->smsg.sending.cb(pif->smsg.sending.msgident,_SUCCESS);} else if (pif->pl.hdlCommSent != NULL) {pif->pl.hdlCommSent(pif->smsg.sending.msgident,_SUCCESS);} #endif flg = true; break; #endif } #if CAN_SEND_FASET_MODE > 0 }while(flg == true && (pif->smsg.step != e_step_fail)); #endif if(flg) can_kill( E_CAN_MSG_SIG,e_sts_needsend,pif->canif.chan); } static void HdlSendMsgError(st_if* pif) { if(pif->smsg.step == e_step_waitack) { M_DEBUGF("[CDCtrl]chan%d第%d(%d)次发送失败\n",pif->canif.chan,pif->smsg.stimes,pif->pl.resendTimes); if(pif->smsg.stimes >= pif->pl.resendTimes) { pif->smsg.step = e_step_fail; } else { pif->smsg.step = e_step_resend; } can_kill( E_CAN_MSG_SIG,e_sts_needsend,pif->canif.chan); } else { M_DEBUGF("[CDCtrl]HdlSendError,当前发送步骤%d!=%d\n",pif->smsg.step,e_step_waitack); } } static void HdlSendMsgSuccess(st_if* pif,unsigned char index) { //M_DEBUGF("[CDCtrl]chan=%d,%o sendOK(%d)\n",pif->canif.chan,index,pif->smsg.step); if(pif->smsg.step == e_step_waitack||pif->smsg.step ==e_step_resend) { if(pif->smsg.sending.sendindex == index) { pif->smsg.step = e_step_suc; #if CAN_SEND_FASET_MODE > 0 if(pif->linkSts >= e_sts_working) HdlAllSengMsgSts(pif); #else can_kill( E_CAN_MSG_SIG,e_sts_needsend,pif->canif.chan); #endif } else { M_DEBUGF("[CDCtrl]chan %d,index :%o#%o\n",pif->canif.chan,index,pif->smsg.sending.sendindex); } } } /********************************************************************************************************************* //CANDRVCTRL 作为传输协议与can驱动之间的中间层,作为一个纽带来将两者进行连接 // ////////////////////////////////////////////////////////////////////////////////////////////////////// // 驱动管理层<------> 传输协议 ************************** ////////////////////////////////////////////////////////////////////////////////////////////////////// //bool InstallProtocalToIF(unsigned char canid, st_pl* pif, st_cl * pcanif); 将某个接口与协议之间进行连接 // 同一时间,一个接口仅仅可以与一个协议进行连接 //参数st_pl, 是协议层需要提供的接口,这些信息在需要的时候被CANDRVCTRL调用 //参数st_cl, 是CANDRVCTRL 提供的接口, 协议层可以通过这些接口进行数据发送等 *********************************************************************************************************************/ static bool plSend(unsigned char chan,unsigned int frmid,unsigned char *data,unsigned char len,unsigned int msgident,void(*cb)(unsigned int msgident,unsigned int result))//若长度为0则表示是远程帧。 { st_senditem send; st_if* pif=NULL; pif=GetIfFromChanel(chan); if(pif ==NULL ||pif->linkSts<=e_sts_closed|| len>8 || sfifo_full(&pif->send)) return false; SYS_ENTER_CRITICAL(); if (pif->linkSts == e_err_bussoff || pif->linkSts < e_sts_working) { SYS_EXIT_CRITICAL(); return false; } send.cb = cb; send.frmid = frmid; send.datalen = len; send.msgident = msgident; if(data == NULL) send.datalen = 0; if(send.datalen>0 && send.datalen<=8) CAN_COPY(send.data,data,send.datalen); send.sendindex = 0xFF; sfifo_write(&pif->send,&send); if(pif->smsg.step == e_step_send_idle) { #if CAN_SEND_FASET_MODE > 0 HdlAllSengMsgSts(pif); #else can_kill( E_CAN_MSG_SIG,e_sts_needsend,pif->canif.chan); #endif } SYS_EXIT_CRITICAL(); return true; } static bool plReceive(unsigned char chan,unsigned int* frmid,unsigned char *data,unsigned char* len)//若长度为0则表示是远程帧。 { st_recitem rec; st_if* pif=GetIfFromChanel(chan); if(pif ==NULL ||pif->linkSts<=e_sts_closed || data==NULL || (pif->pl.flg&CAN_FLG_SYNCRECEIVE)) return false; if(sfifo_empty(&pif->rec)) return false; if(sfifo_read(&pif->rec,&rec)==0) return false; *frmid = rec.frmid; *len = rec.datalen; if(rec.datalen > 0 && rec.datalen<=8) CAN_COPY(data,rec.data,rec.datalen); if (pif->linkSts == e_err_overfllow) { pif->linkSts = e_sts_working; } return true; } static unsigned int plGetCurrentLinkSts(unsigned char chan) //获取当前链状态 { st_if* pif=NULL; pif=GetIfFromChanel(chan); if(pif !=NULL) return pif->linkSts; return 0; } static bool plConfigBus(unsigned char chan,unsigned short krate, bool highdomain,bool listen) { st_if* pif=GetIfFromChanel(chan); if(pif ==NULL ||pif->linkSts<=e_sts_unused) return false; if(pif->canif.ConfigCan != NULL) { if(pif->canif.ConfigCan(chan,krate,highdomain,listen)) { if(pif->psend != NULL) { sfifo_init(&pif->send,pif->psend,sizeof(st_senditem),pif->pl.msgNumber); } if((pif->pl.flg&CAN_FLG_SYNCRECEIVE)==0 && (pif->prec != NULL)) { sfifo_init(&pif->rec,pif->prec,sizeof(st_recitem),pif->pl.msgNumber); } pif->linkSts = e_sts_working; return true; } } return false; } static bool plcanBusFilterInit(unsigned char chan,unsigned int *filterID_array, unsigned short filterID_total) { return false; } static bool plCloseLink(unsigned char chan) { st_if* pif=GetIfFromChanel(chan); if(pif ==NULL ||pif->linkSts<=e_sts_closed) return false; pif->linkSts = e_sts_closed; if(pif->canif.canClose != NULL) pif->canif.canClose(chan); if(pif->smsg.step != e_step_send_idle) { if(pif->smsg.sending.cb != NULL) { if(pif->smsg.step == e_step_suc) { pif->smsg.sending.cb(pif->smsg.sending.msgident,_SUCCESS); } else if(pif->smsg.step == e_step_fail) { pif->smsg.sending.cb(pif->smsg.sending.msgident,_FAILURE); } else { pif->smsg.sending.cb(pif->smsg.sending.msgident,_ABANDON); } } else if (pif->pl.hdlCommSent != NULL) { if(pif->smsg.step == e_step_suc) { pif->pl.hdlCommSent(pif->smsg.sending.msgident,_SUCCESS); } else if(pif->smsg.step == e_step_fail) { pif->pl.hdlCommSent(pif->smsg.sending.msgident,_FAILURE); } else { pif->pl.hdlCommSent(pif->smsg.sending.msgident,_ABANDON); } } } while(sfifo_empty(&(pif->send))==false) { if(sfifo_read(&(pif->send),&(pif->smsg.sending))) { if(pif->smsg.sending.cb != NULL) pif->smsg.sending.cb(pif->smsg.sending.msgident,_ABANDON); else if (pif->pl.hdlCommSent != NULL) {pif->pl.hdlCommSent(pif->smsg.sending.msgident,_ABANDON);} } } memset(&pif->smsg,0x00,sizeof(pif->smsg)); return true; } //////////////////////////////////////////////////////////////////////////////////////////// //CanDrvCtrl 模块消息处理部分 //////////////////////////////////////////////////////////////////////////////////////////// static void hdlCanCtrlMsg(e_link_sts msg,unsigned char chan) { st_if* pif=GetIfFromChanel(chan); if(pif == NULL) return; switch(msg) { case e_sts_needsend: if(pif->linkSts >= e_sts_working) HdlAllSengMsgSts(pif); break; case e_err_overfllow: if(pif->linkSts >= e_sts_working && pif->pl.hdlBusError!= NULL) { pif->pl.hdlBusError(e_err_overfllow); } break; case e_err_receive: if(pif->linkSts >= e_sts_working && pif->pl.hdlBusError!= NULL) { pif->pl.hdlBusError(e_err_receive); } break; case e_err_sending: if(pif->linkSts >= e_sts_working) { HdlSendMsgError(pif); if(pif->pl.hdlBusError!= NULL)pif->pl.hdlBusError(e_err_sending); } break; case e_err_bussoff: if(pif->linkSts >= e_sts_working) { if(pif->smsg.step == e_step_waitack) { pif->smsg.step = e_step_fail; can_kill( E_CAN_MSG_SIG,e_sts_needsend,pif->canif.chan); } if(pif->pl.hdlBusError!= NULL) { pif->pl.hdlBusError(e_err_bussoff); } else { plCloseLink(pif->canif.chan); plConfigBus(pif->canif.chan, 0, 0, 0); } } break; default: //达到这里则出错 break; } } static void CAN_MSG_SIG_FUNC(unsigned int signal, int para1, int para2) { hdlCanCtrlMsg(para1, para2); } static void CAN_MSG_CB_SIG_FUNC(unsigned int signal, int para1, int para2) { void (*hdlCommSent)(unsigned int canid, unsigned int result); hdlCommSent = (void *)para1; if (hdlCommSent != NULL) { hdlCommSent(para2, _SUCCESS); } } //协议层需要提供能接口 bool InstallProtocalToIF(unsigned char chan, st_pl* ppl, st_cl * pcl) { st_if* pif = NULL; st_pl *p_pl; pif=GetIfFromChanel(chan); if(pif == NULL || ppl == NULL||pcl==NULL) return false; if(ppl->prompt[0]== 0 || pif->linkSts != e_sts_unused) { M_DEBUGF("[CDCtrl]InstallProtocalToIF:协议名字为空或接口已安装有协议(%d)\n",pif->linkSts); return false; } if((ppl->flg&CAN_FLG_SYNCRECEIVE) && ppl->hdlRecCanMsg == NULL) { M_DEBUGF("[CDCtrl]InstallProtocalToIF: 未提供hdlRecCanMsg 接口\n"); return false; } pif->pl.msgNumber = ppl->msgNumber; if(pif->pl.msgNumber == 0) pif->pl.msgNumber=50; //默认是50 pif->psend = CAN_MALLOC(sizeof(st_senditem)*pif->pl.msgNumber); if(pif->psend != NULL) { sfifo_init(&pif->send,pif->psend,sizeof(st_senditem),pif->pl.msgNumber); } else { M_DEBUGF("[CDCtrl]InstallProtocalToIF:内存分配失败,请求分配内存空间%d*%d\n",sizeof(st_senditem),pif->pl.msgNumber); return false; } if((ppl->flg&CAN_FLG_SYNCRECEIVE)==0) { pif->prec = CAN_MALLOC(sizeof(st_recitem)*pif->pl.msgNumber); if(pif->prec != NULL) { sfifo_init(&pif->rec,pif->prec,sizeof(st_recitem),pif->pl.msgNumber); } else { CAN_FREE(pif->psend); pif->psend = NULL; M_DEBUGF("[CDCtrl]InstallProtocalToIF:内存分配失败,请求分配内存空间%d*%d\n",sizeof(st_senditem),pif->pl.msgNumber); return false; } } pif->pl.flg = ppl->flg; p_pl = &(pif->pl); memset(p_pl->prompt,0x00,sizeof(ppl->prompt)); CAN_COPY(p_pl->prompt,ppl->prompt,sizeof(ppl->prompt)-1); p_pl->hdlBusError = ppl->hdlBusError; p_pl->hdlRecCanMsg= ppl->hdlRecCanMsg; p_pl->resendTimes = ppl->resendTimes; p_pl->hdlCommSent = ppl->hdlCommSent; pcl->canBusFilterInit = plcanBusFilterInit; pcl->ConfigBus = plConfigBus; pcl->GetCurrentLinkSts = plGetCurrentLinkSts; pcl->REC = plReceive; pcl->SEND = plSend; pcl->CloseLink = plCloseLink; pif->linkSts = e_sts_closed; return true; } bool UninstallProtocalToIF(unsigned char chan, st_pl* ppl) { st_if* pif=NULL; pif=GetIfFromChanel(chan); if(ppl == NULL || pif == NULL) return false; if(CAN_CMPY(ppl->prompt,pif->pl.prompt,sizeof(ppl->prompt)-1) != 0) { M_DEBUGF("协议层接口指针不匹配\n"); return false; } //将状态切换到未使用状态 pif->linkSts = e_sts_unused; if(pif->canif.canCloseFilter != NULL) { pif->canif.canCloseFilter(chan); } if(pif->canif.canClose != NULL) { pif->canif.canClose(chan); } //释放空间 if((pif->pl.flg&CAN_FLG_SYNCRECEIVE)==0 && pif->prec != NULL) { CAN_FREE(pif->prec); pif->prec = NULL; } if(pif->psend != NULL) { CAN_FREE(pif->psend); pif->psend = NULL; } memset(&pif->pl,0x00,sizeof(st_pl)); memset(&pif->smsg,0x00,sizeof(st_sendmsg)); return true; } void InitCanDrvCtrlMode(void) { unsigned char i; for(i=0;i 0 #if 0 const static char* stsprompt[]={ "e_sts_empty", "e_sts_unused", "e_sts_closed", "e_sts_working", }; const static char* errprompt[]={ "e_err_receive", "e_err_sending", "e_err_overfllow", }; void DprintCanDrvCtrl(void) { unsigned char i; for(i=0;i e_sts_unused) { M_DEBUGF("\tprotocol:%s\n",CanIF[i].pl.prompt); } M_DEBUGF("\tMsg Step:%d\n",CanIF[i].smsg.step); } } #endif