/*
Copyright (C) 2008 - Nari-Relays Electric CO.,Ltd.
* Chen Weiyuan, UAPC GROUP, chenwy@nari-relays.com.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*/
/*
* transmit buffer0 is used to send ack frames;
* transmit buffer1 is used to send single app frames;
* transmit buffer2 is used to send multi frames;
*/
#include <common.h>
#include <mpc5xxx.h>
#include "candrv.h"
// ------------------------------------------------------------------------------------------------
// Global Variables
// ------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------//
// Define Global Variable for buf
//--------------------------------------------------------------------------//
struct MultiFrameBuf MFTXBuf; // 多帧报文发送缓冲区
struct SingleFrameBuf SFTXBuf; // 单帧报文发送缓冲区
struct AckFrameBuf ACKTXBuf; // 应答帧报文发送缓冲区
struct MSFRXSTATUS MSRStatus; // 多帧或单帧报文接收状态,应用程序处理报文的接口
struct CANSTATUS CanStatus; // CAN状态
struct CANERRORSTAT CanError; // CAN错误
union CANMSGID_REG CanMbidBuf[2]; // 帧ID
struct SingleFrame SFRXBuf; // 单帧报文接收缓冲区
struct MultiFrameBuf MFRXBuf; // 多帧报文接收缓冲区
unsigned char mcpu_address;
unsigned char my_address; // 本板地址
u8 rev_mframe_num;
void can_isr(void);
extern void appMsgProcess(u8 appType,u8 source,int dataLen,char *data);
/*********************************************************************
* Function: initCanBuf
* Description: 初始化CAN报文的缓冲区
* Input: Null
* Return: Null
**********************************************************************/
static void initCanBuf(void)
{
MFTXBuf.id.all = 0; // 初始化多帧发送报文缓冲区
MFTXBuf.len = 0;
MFTXBuf.pointer = 0;
SFTXBuf.in = 0; // 初始化单帧发送报文缓冲区
SFTXBuf.out= 0;
ACKTXBuf.in = 0; // 初始化应答帧发送报文缓冲区
ACKTXBuf.out = 0;
memset((void*)&CanStatus, 0, sizeof(CanStatus));
memset((void*)&CanError, 0, sizeof(CanError)); // CAN的错误信息
}
/*********************************************************************
* Function: initCan
* Description: 初始化CAN模块
* Input: Null
* Return: Null
**********************************************************************/
void initCan(u8 can_num)
{
struct mpc5xxx_mscan *regs;
if(can_num == 0)
regs = (struct mpc5xxx_mscan*)MPC5xxx_MSCAN1;
else if(can_num == 1)
regs = (struct mpc5xxx_mscan*)MPC5xxx_MSCAN2;
else return;
// Enable MSCAN module.
regs->canctl1 |= MPC5xxx_MSCAN_CANE;
udelay(100);
// Switch to sleep mode
regs->canctl0 |= MPC5xxx_MSCAN_SLPRQ;
while (!(regs->canctl1 & MPC5xxx_MSCAN_SLPAK));
// Switch to initialization mode.
regs->canctl0 |= MPC5xxx_MSCAN_INITRQ;
while (!(regs->canctl1 & MPC5xxx_MSCAN_INITAK));
regs->canctl1 &= ~MPC5xxx_MSCAN_LISTEN;
// Set bus baudrate=1Mbps.
regs->canbtr0 = CAN_BAUD_1M >> 8;
regs->canbtr1 = CAN_BAUD_1M&0xFF;
// Choose IP bus as clock source.
regs->canctl1 &= ~MPC5xxx_MSCAN_CLKSRC;
// we have initialized the fpga,so we can read board address
my_address = *(unsigned long*)(CFG_FPGA_BASE+(0x80C << 2));
my_address >>= 1;
printf("my_address=%d\n",my_address);
// Configure MSCAN acceptance and mask regs
regs->canidar0 = 0x00;
regs->canidar1 = 0x00;
regs->canidar2 = 0x00;
regs->canidar3 = my_address << 1;
regs->canidmr0 = 0xFF;
regs->canidmr1 = 0xFF;
regs->canidmr2 = 0xFF;
regs->canidmr3 = 0x01;
regs->canidar4 = 0x00;
regs->canidar5 = 0x00;
regs->canidar6 = 0x00;
regs->canidar7 = my_address << 1;
regs->canidmr4 = 0xFF;
regs->canidmr5 = 0xFF;
regs->canidmr6 = 0xFF;
regs->canidmr7 = 0x01;
//32-bit Acceptance Filters
regs->canidac &= ~(MPC5xxx_MSCAN_IDAM0 | MPC5xxx_MSCAN_IDAM1);
// Switch back to normal mode.
regs->canctl0 &= ~MPC5xxx_MSCAN_INITRQ;
regs->canctl0 &= ~MPC5xxx_MSCAN_SLPRQ;
while((regs->canctl1 & MPC5xxx_MSCAN_INITAK) ||
(regs->canctl1 & MPC5xxx_MSCAN_SLPAK));
// Enable rx and overrun interrupts.
regs->canrier |= MPC5xxx_MSCAN_OVRIE | MPC5xxx_MSCAN_RXFIE ;
initCanBuf();
irq_install_handler(MPC5XXX_MSCAN1_IRQ,(interrupt_handler_t *)can_isr,NULL);
printf("irq=%d int mask=%lx \n",MPC5XXX_MSCAN1_IRQ,*(volatile unsigned long*)(CFG_MBAR+0x500));
}
/*********************************************************************
* Function: getFrameType
* Description: 从应用类型得到帧类型
* Input: AppType
* Return: FrameType
**********************************************************************/
unsigned char getFrameType(unsigned char app_type, unsigned char sub_type)
{
if ( (app_type < ORDER_STATUS_TYPE) ||
(app_type==VAR_MANAGEMENT_TYPE && sub_type==SEND_VARVALUE_DEBUG_TYPE) )
return NEEDLESS_ACK_FRAME; // 无应答类型
return NEED_ACK_FRAME; // 有应答类型
}
/*********************************************************************
* Function: sendAck
* Description:
* Input: 目标地址, 应答类型,帧类型,数据报文首地址
* Return: Null
**********************************************************************/
void sendAck(u8 dest, u8 AppType, u8 FrameType, u8 data, u8 sf_cyc_no, char can_num)
{
union CANMSGID_REG CanMbid; // CAN MailBox ID
struct mpc5xxx_mscan *regs;
if(can_num == 0)
regs = (struct mpc5xxx_mscan*)MPC5xxx_MSCAN1;
else if(can_num == 1)
regs = (struct mpc5xxx_mscan*)MPC5xxx_MSCAN2;
else return;
CanMbid.all = 0;
CanMbid.bit.IDE = 1; // 29bit ID
CanMbid.bit.SRR = 1;
CanMbid.bit.Priority = 1; // Higt priority
CanMbid.bit.CycNo = sf_cyc_no;
CanMbid.bit.FrameType = FrameType; // Frame type: 00-11
// CanMbid.bit.VSQ = 0; // Vsq
// CanMbid.bit.Rtr = 0; // Disable RTR
CanMbid.bit.AppType0_1 = AppType&0x3; // Application type
CanMbid.bit.AppType2_4 = (AppType & 0x1C) >> 2;
CanMbid.bit.FrameFlag = 1; // Single Frame
CanMbid.bit.Source = my_address; // Source address
CanMbid.bit.Finish = 1; // Finish flag
CanMbid.bit.Destination = dest; // Desination address
if(((regs->cantflg) & MPC5xxx_MSCAN_TXE0) == MPC5xxx_MSCAN_TXE0) // 判断上次的发送是否完成
{
regs->cantbsel = MPC5xxx_MSCAN_TX0;
regs->cantxfg.idr[0] = (CanMbid.all >> 24) & 0xFF;
regs->cantxfg.idr[1] = (CanMbid.all >> 16) & 0xFF;
regs->cantxfg.idr[4] = (CanMbid.all >> 8) & 0xFF;
regs->cantxfg.idr[5] = CanMbid.all & 0xFF;
regs->cantxfg.dlr = 1; //Data Length
regs->cantxfg.tbpr = 0; //priority
regs->cantxfg.dsr[0] = data;
regs->cantflg = MPC5xxx_MSCAN_TXE0; // to send buffer 0
regs->cantier |= MPC5xxx_MSCAN_TXIE0; //enable tx0 int
}
else
{
if (((ACKTXBuf.in+1) & (MAX_ACKBUF-1)) == ACKTXBuf.out) // 缓冲区是否已满