325 lines
6.8 KiB
C
325 lines
6.8 KiB
C
/***********************************************************************
|
||
* @file name: canbusdrv.c
|
||
* @create date: 2022-11-12
|
||
* @author
|
||
* @version: V 1.0.0
|
||
* @remark:
|
||
这个模块对can外设进行统一管理,忽略MCU接口的不同,对外一个统一的接口
|
||
MCU的更换不涉及到这里
|
||
************************************************************************/
|
||
#include <stdio.h>
|
||
#include <stdbool.h>
|
||
#include "canbusdrv.h"
|
||
#include "candrvctrl.h"
|
||
|
||
/**
|
||
* 这个模块对can外设进行统一管理,忽略MCU接口的不同,对外一个统一的接口
|
||
* MCU的更换不涉及到这里
|
||
*/
|
||
/**
|
||
* 模块统一完成,总线的中断收发,和异常处理
|
||
*/
|
||
|
||
static st_cancb tpcb[2];
|
||
|
||
/*****************************************************************************************
|
||
* can 接收发送队列的处理
|
||
*****************************************************************************************/
|
||
|
||
|
||
typedef struct{
|
||
bsp_can_cfg_t bsp_cfg; /* can 的配置 */
|
||
unsigned int open_flg; /* 打开标志 0 - 关闭 1-打开中 2-已打开*/
|
||
unsigned int sending; /* 正在发送的flag */
|
||
can_frame_t tmp_frame; /* 临时报文 */
|
||
}can_bus_t;
|
||
|
||
|
||
static can_bus_t canbus[BSP_CAN_CHANNEL_NUM]={0};
|
||
|
||
|
||
static __inline void can_bus_ready_hook(unsigned char channel)
|
||
{
|
||
if (channel >= BSP_CAN_CHANNEL_NUM) {
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: 接收到消息的HOOK
|
||
*
|
||
* @param channel: 通道号
|
||
* @param pt_fram[IN]: 接收到的消息内容
|
||
*
|
||
* @return:
|
||
*/
|
||
void bsp_can_msg_receive_hook(unsigned char channel, const can_frame_t * pt_fram)
|
||
{
|
||
|
||
if (channel >= BSP_CAN_CHANNEL_NUM)
|
||
{
|
||
return;
|
||
}
|
||
if(tpcb[channel].hdlFrmReceve != NULL)
|
||
{
|
||
tpcb[channel].hdlFrmReceve(channel,(pt_fram->IDE == CAN_ID_EXT)?pt_fram->ExtId:pt_fram->StdId, pt_fram->Data, pt_fram->DLC);
|
||
}
|
||
can_bus_ready_hook(channel);
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: 发送消息完成的hook
|
||
*
|
||
* @param channel: 通道号
|
||
* @param fifo_id: 消息空的ID
|
||
* @param success: true 发送成功, false 发送失败
|
||
*
|
||
* @return: void
|
||
*
|
||
* @remark: 发送FIFO空的hook
|
||
*/
|
||
void bsp_can_msg_sent_hook(unsigned char channel, unsigned char fifo_id, bool success)
|
||
{
|
||
unsigned char ret_id;
|
||
|
||
if (channel >= BSP_CAN_CHANNEL_NUM)
|
||
{
|
||
return;
|
||
}
|
||
|
||
/* 判断是否正在发送 */
|
||
if (canbus[channel].sending&(0x00000001<<fifo_id))
|
||
{
|
||
canbus[channel].sending &= ~(0x00000001<<fifo_id);
|
||
can_bus_ready_hook(channel);
|
||
if(tpcb[channel].SendSuccessCb != NULL)
|
||
{
|
||
tpcb[channel].SendSuccessCb(channel,fifo_id);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
/***************************************************************************
|
||
* 下面是对总线异常的处理
|
||
**************************************************************************/
|
||
|
||
/**
|
||
* @brief: 总线BUS OFF错误的hook函数
|
||
*
|
||
* @param channel: can 通道, 应该是 CAN1_CHANNEL 或者 CAN2_CHANNEL
|
||
*
|
||
* @return: void
|
||
*
|
||
* @remark: 当总线打开成功时被调用
|
||
*/
|
||
void can_bus_off_hook(unsigned char channel)
|
||
{
|
||
|
||
if (channel >= BSP_CAN_CHANNEL_NUM) {
|
||
return;
|
||
}
|
||
|
||
SYS_ENTER_CRITICAL();
|
||
if(tpcb[channel].BusOffCb != NULL)
|
||
{
|
||
tpcb[channel].BusOffCb(channel);
|
||
}
|
||
SYS_EXIT_CRITICAL();
|
||
if (canbus[channel].sending > 0)
|
||
{
|
||
/* 说明有发送失败的,针对发送失败的后续处理暂留 */
|
||
canbus[channel].sending = 0;
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: 总线切换错误消极回应状态hook函数
|
||
*
|
||
* @param channel: can 通道,
|
||
*
|
||
* @return: void
|
||
*
|
||
* @remark: 当总线应答切换未消极应答时触发,一般是
|
||
*/
|
||
void can_bus_err_passive_hook(unsigned char channel)
|
||
{
|
||
if (channel >= BSP_CAN_CHANNEL_NUM) {
|
||
return;
|
||
}
|
||
|
||
if(tpcb[channel].BusErrorStsCb != NULL)
|
||
{
|
||
tpcb[channel].BusErrorStsCb(channel, canbus[channel].sending > 0?true:false);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief: 异步发送数据报文
|
||
*
|
||
* @param chan: can 通道号
|
||
* @param canid: 报文ID
|
||
* @param data[IN]: 数据内容
|
||
* @param len: 数据长度
|
||
*
|
||
* @return 返回是否成功。
|
||
* true: 成功 false: 失败
|
||
*/
|
||
bool can_bus_send(unsigned char chan,unsigned int canid,const unsigned char *data, unsigned char len)
|
||
{
|
||
can_frame_t tmp;
|
||
|
||
if (chan >= BSP_CAN_CHANNEL_NUM)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
CAN_FRAME_INIT(&tmp, canid, data, len);
|
||
|
||
|
||
bsp_can_msg_sent_hook(chan, 0, true);
|
||
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief: 立即发送数据报文
|
||
*
|
||
* @param chan: can 通道号
|
||
* @param canid: 报文ID
|
||
* @param data[IN]: 数据内容
|
||
* @param len: 数据长度
|
||
*
|
||
* @return 返回标识号,0xFF 标识失败
|
||
*/
|
||
unsigned char can_bus_send_rt(unsigned char chan,unsigned int canid,const unsigned char *data, unsigned char len)
|
||
{
|
||
unsigned char ret_id;
|
||
|
||
if (chan >= BSP_CAN_CHANNEL_NUM || canbus[chan].open_flg != 2)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
CAN_FRAME_INIT(&canbus[chan].tmp_frame, canid, data, len);
|
||
|
||
ret_id = bsp_can_msg_send(chan, &canbus[chan].tmp_frame);
|
||
|
||
if (ret_id != 0xFF)
|
||
{
|
||
canbus[chan].sending |= (0x00000001<<ret_id);
|
||
}
|
||
|
||
return ret_id;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: 打开总线
|
||
*
|
||
* @param chan: can通道
|
||
* @param krate: 速率
|
||
* @param highdomain: 高电平信号
|
||
* @param listen: 是否为监听模式
|
||
*
|
||
* @return:
|
||
* true: 成功 false 失败
|
||
*/
|
||
bool can_bus_open(unsigned char chan,unsigned short krate, bool highdomain, bool listen)
|
||
{
|
||
if (chan >= BSP_CAN_CHANNEL_NUM)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
canbus[chan].open_flg = 1;
|
||
canbus[chan].bsp_cfg.abom = false;
|
||
canbus[chan].bsp_cfg.sleep = listen;
|
||
canbus[chan].bsp_cfg.domain_h = highdomain;
|
||
canbus[chan].bsp_cfg.krate = krate;
|
||
|
||
canbus[chan].sending = 0;
|
||
if (bsp_can_open(chan, &canbus[chan].bsp_cfg))
|
||
{
|
||
canbus[chan].open_flg = 2;
|
||
}
|
||
else
|
||
{
|
||
canbus[chan].open_flg = 0;
|
||
}
|
||
return canbus[chan].open_flg == 2;
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief: 关闭接口
|
||
*
|
||
* @return:
|
||
* 返回结果: true - open 成功 false - open 失败
|
||
*/
|
||
bool can_bus_close(unsigned char channel)
|
||
{
|
||
canbus[channel].open_flg = 0;
|
||
bsp_can_close(channel);
|
||
}
|
||
|
||
|
||
|
||
static const st_canif tpchan[] =
|
||
{
|
||
{
|
||
0, //chan1
|
||
can_bus_open, //ConfigCan
|
||
can_bus_send_rt, //canSend
|
||
can_bus_close, //canClose
|
||
NULL, //canHwPowerDown
|
||
NULL, //canHwPowerUp
|
||
NULL, //canBusFilterInit
|
||
NULL, //canCloseFilter
|
||
},
|
||
|
||
{
|
||
1, //chan2
|
||
can_bus_open, //ConfigCan
|
||
can_bus_send_rt, //canSend
|
||
can_bus_close, //canClose
|
||
NULL, //canHwPowerDown
|
||
NULL, //canHwPowerUp
|
||
NULL, //canBusFilterInit
|
||
NULL, //canCloseFilter
|
||
},
|
||
};
|
||
|
||
|
||
|
||
void InitCanifToCanDrvCtrl(void)
|
||
{
|
||
st_cancb *pcb;
|
||
|
||
memset(&canbus[0], 0x00, sizeof(canbus));
|
||
memset(&tpcb[0], 0x00, sizeof(tpcb));
|
||
|
||
pcb = RegisterCanIF(&tpchan[0]);
|
||
if(pcb!=NULL)
|
||
memcpy(&tpcb[0],pcb,sizeof(st_cancb)); /* 下标要与st_canif.chan 一致 */
|
||
|
||
pcb = RegisterCanIF(&tpchan[1]);
|
||
if(pcb!=NULL)
|
||
memcpy(&tpcb[1],pcb,sizeof(st_cancb)); /* 下标要与st_canif.chan 一致 */
|
||
}
|
||
|
||
|
||
|
||
//#endif
|
||
|