#ifndef __MCP2515_H
#define __MCP2515_H /*
mcp2515.h This file contains constants that are specific to the MCP2515. Version Date Description
----------------------------------------------------------------------
v1.00 2003/12/11 Initial release Copyright 2003 Kimberly Otten Software Consulting
*/ // Define MCP2515 register addresses #define MCP_RXF0SIDH 0x00
#define MCP_RXF0SIDL 0x01
#define MCP_RXF0EID8 0x02
#define MCP_RXF0EID0 0x03
#define MCP_RXF1SIDH 0x04
#define MCP_RXF1SIDL 0x05
#define MCP_RXF1EID8 0x06
#define MCP_RXF1EID0 0x07
#define MCP_RXF2SIDH 0x08
#define MCP_RXF2SIDL 0x09
#define MCP_RXF2EID8 0x0A
#define MCP_RXF2EID0 0x0B
#define MCP_CANSTAT 0x0E
#define MCP_CANCTRL 0x0F
#define MCP_RXF3SIDH 0x10
#define MCP_RXF3SIDL 0x11
#define MCP_RXF3EID8 0x12
#define MCP_RXF3EID0 0x13
#define MCP_RXF4SIDH 0x14
#define MCP_RXF4SIDL 0x15
#define MCP_RXF4EID8 0x16
#define MCP_RXF4EID0 0x17
#define MCP_RXF5SIDH 0x18
#define MCP_RXF5SIDL 0x19
#define MCP_RXF5EID8 0x1A
#define MCP_RXF5EID0 0x1B
#define MCP_TEC 0x1C
#define MCP_REC 0x1D
#define MCP_RXM0SIDH 0x20
#define MCP_RXM0SIDL 0x21
#define MCP_RXM0EID8 0x22
#define MCP_RXM0EID0 0x23
#define MCP_RXM1SIDH 0x24
#define MCP_RXM1SIDL 0x25
#define MCP_RXM1EID8 0x26
#define MCP_RXM1EID0 0x27
#define MCP_CNF3 0x28
#define MCP_CNF2 0x29
#define MCP_CNF1 0x2A
#define MCP_CANINTE 0x2B
#define MCP_CANINTF 0x2C
#define MCP_EFLG 0x2D
#define MCP_TXB0CTRL 0x30
#define MCP_TXB1CTRL 0x40
#define MCP_TXB2CTRL 0x50
#define MCP_RXB0CTRL 0x60
#define MCP_RXB0SIDH 0x61
#define MCP_RXB1CTRL 0x70
#define MCP_RXB1SIDH 0x71 #define MCP_TX_INT 0x1C // Enable all transmit interrupts
#define MCP_TX01_INT 0x0C // Enable TXB0 and TXB1 interrupts
#define MCP_RX_INT 0x03 // Enable receive interrupts
#define MCP_NO_INT 0x00 // Disable all interrupts #define MCP_TX01_MASK 0x14
#define MCP_TX_MASK 0x54 // Define SPI Instruction Set #define MCP_WRITE 0x02 #define MCP_READ 0x03 #define MCP_BITMOD 0x05 #define MCP_LOAD_TX0 0x40
#define MCP_LOAD_TX1 0x42
#define MCP_LOAD_TX2 0x44 #define MCP_RTS_TX0 0x81
#define MCP_RTS_TX1 0x82
#define MCP_RTS_TX2 0x84
#define MCP_RTS_ALL 0x87 #define MCP_READ_RX0 0x90
#define MCP_READ_RX1 0x94 #define MCP_READ_STATUS 0xA0 #define MCP_RX_STATUS 0xB0 #define MCP_RESET 0xC0 // CANCTRL Register Values #define MODE_NORMAL 0x00
#define MODE_SLEEP 0x20
#define MODE_LOOPBACK 0x40
#define MODE_LISTENONLY 0x60
#define MODE_CONFIG 0x80
#define MODE_POWERUP 0xE0
#define MODE_MASK 0xE0
#define ABORT_TX 0x10
#define MODE_ONESHOT 0x08
#define CLKOUT_ENABLE 0x04
#define CLKOUT_DISABLE 0x00
#define CLKOUT_PS1 0x00
#define CLKOUT_PS2 0x01
#define CLKOUT_PS4 0x02
#define CLKOUT_PS8 0x03 // CNF1 Register Values #define SJW1 0x00
#define SJW2 0x40
#define SJW3 0x80
#define SJW4 0xC0 // CNF2 Register Values #define BTLMODE 0x80
#define SAMPLE_1X 0x00
#define SAMPLE_3X 0x40 // CNF3 Register Values #define SOF_ENABLE 0x80
#define SOF_DISABLE 0x00
#define WAKFIL_ENABLE 0x40
#define WAKFIL_DISABLE 0x00 // CANINTF Register Bits #define MCP_RX0IF 0x01
#define MCP_RX1IF 0x02
#define MCP_TX0IF 0x04
#define MCP_TX1IF 0x08
#define MCP_TX2IF 0x10
#define MCP_ERRIF 0x20
#define MCP_WAKIF 0x40
#define MCP_MERRF 0x80 #endif
/**********************************************************************/
/* */
/* File name: drv_mcp2515.c */
/* */
/* Since: 2005-Nov-30 */
/* */
/* Version: PICos18 v2.04 */
/* Copyright (C) 2003, 2004, 2005 Pragmatec. */
/* MCP2515 CAN driver v1.00 */
/* */
/* Author: Designed by Pragmatec S.A.R.L. www.pragmatec.net */
/* ROZIER Bertrand [RZR] bertrand.rozier@pragmatec.net */
/* */
/* Purpose: MCP2515 : SPI CAN controller management. */
/* It allows task tosend data at the send time through a */
/* dedicated FIFO, and to wait for a certain CAN frame. */
/* */
/* Distribution: This file is part of PICos18. */
/* PICos18 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, or (at your option) */
/* any later version. */
/* */
/* PICos18 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 gpsim; see the file */
/* COPYING.txt. If not, write to the Free Software */
/* Foundation, 59 Temple Place - Suite 330, */
/* Boston, MA 02111-1307, USA. */
/* */
/* > A special exception to the GPL can be applied should */
/* you wish to distribute a combined work that includes */
/* PICos18, without being obliged to provide the source */
/* code for any proprietary components. */
/* */
/* History: */
/* 2005/11/30 [RZR] Create this file */
/**********************************************************************/ #include "define.h"
#include "drv_mcp2515.h"
#include "drv_spi.h" #define MCP2515_CS_PORT PORTC
#define MCP2515_CS_BIT 0 /**********************************************************************
* Definition dedicated to the local functions.
**********************************************************************/
void MCP2515_Init(void);
void MCP2515_Config(void);
void MCP2515_Reset(void);
void MCP2515_GetStatus(void);
void MCP2515_SetMode(unsigned char mode);
void MCP2515_BitModify(unsigned char addr, unsigned char mask, unsigned char data);
void MCP2515_ByteWrite(unsigned char addr, unsigned char data);
void MCP2515_ByteRead(unsigned char addr, unsigned char * pdata);
void MCP2515_RTS(unsigned char buffer_TX);
void MCP2515_ReadRXbuffer0(void);
void MCP2515_ReadRXbuffer1(void);
void ManageISR(void); StatusType mcp2515_write_buffer(unsigned char registre, unsigned char *pdata); EventMaskType CAN_event; CAN_message_tRef CAN_list_head; // Start of message queue
CAN_message_tRef CAN_current_message; // Current message
unsigned char CAN_list_count = ; // Number of items currently in queue CAN_message_tRef CAN_list_head_rcv; // Start of message queue
CAN_message_tRef CAN_current_message_rcv;// Current message
unsigned char CAN_list_count_rcv = ; // Number of items currently in queue SPI_message_t SPI_MCP2515; TXBn_t TXB0,TXB1,TXB2;
TXBn_tRef pTXBn;
RXBn_t RXB0,RXB1;
RXBn_tRef pRXBn; // Local mcp2515 control register
unsigned char CANSTAT;
unsigned char CANCTRL;
unsigned char CNF1;
unsigned char CNF2;
unsigned char CNF3;
unsigned char TXRTSCTRL;
unsigned char CANINTE;
unsigned char CANINTF;
unsigned char EFLG;
unsigned char RXB0CTRL; unsigned char mcp2515_cmd[]; // Fort debug only
#define ALARM_MCP2515 1 /**********************************************************************
* Task of the CAN driver, waiting for any of these 4 events :
* CAN_TX_EVENT : A message has been sent then a hardware transmitter
* is free. The driver will tranfer a software buffer
* into a free TX[0,1,2] hardware buffer.
* CAN_RX_EVENT : A message is arrived in the RX[0,1] buffer.
* the driver transfer the *§bjjcontent of the message into
* a software buffer waiting for this message ID or
* discard the message to free the hardware.
* CAN_ERR_EVENT : Something wrong appended and the driver must clean
* the hardware before being disconnected. To be
* completed...
* ALARM_EVENT : Sometimes a task waiting for a specific message is
* not fast enough to read all the content of the
* hardware buffers. The driver have to keep available
* this content the time needed by other tasks.
* Then the driver periodicaly checks if the other tasks
* have finished to read the hardware buffers or needs
* more time.
*
* @param void
* @return void
**********************************************************************/
TASK(MCP2515_Drv)
{ MCP2515_Init();
MCP2515_Config(); // Just for cyclique update of CAN register
// useful until on debug
// SetRelAlarm(ALARM_MCP2515, 500, 500); while()
{ WaitEvent(CAN_NEW_MSG | CAN_RCV_MSG | CAN_ERR_MSG | MCP2515_IRQ_REQUEST | ALARM_EVENT);
GetEvent(MCP2515_DRV_ID, &CAN_event); if (CAN_event & ALARM_EVENT)
{
ClearEvent(ALARM_EVENT);
// Mainly for debug
MCP2515_ByteRead(CAN2510_REG_CANINTF, &CANINTF);
MCP2515_ByteRead(CAN2510_REG_EFLG, &EFLG);
MCP2515_GetStatus();
} if (CAN_event & CAN_NEW_MSG)
{
ClearEvent(CAN_NEW_MSG);
CopyFrameBuffer2Hard();
} if (CAN_event & CAN_RCV_MSG)
{
ClearEvent(CAN_RCV_MSG);
CopyHard2FrameBuffer();
} if (CAN_event & CAN_ERR_MSG)
{
ClearEvent(CAN_ERR_MSG);
} if (CAN_event & MCP2515_IRQ_REQUEST)
{
ClearEvent(MCP2515_IRQ_REQUEST);
// Get back the flag code
MCP2515_ByteRead(CAN2510_REG_CANINTF, &CANINTF);
MCP2515_ByteRead(CAN2510_REG_EFLG, &EFLG);
MCP2515_GetStatus(); if ( CANINTF & 0x01) // RXB0 full
{
// Clear the flag
MCP2515_BitModify(CAN2510_REG_CANINTF, 0x01, 0x00);
// Clear the local variable
CANINTF &= 0xFE;
// Get RX buffer
MCP2515_ReadRXbuffer0();
SetEvent(MCP2515_DRV_ID,CAN_RCV_MSG);
}
if ( CANINTF & 0x02) // RXB1 full
{
// Clear the flag
MCP2515_BitModify(CAN2510_REG_CANINTF, 0x02, 0x00);
// Clear the local variable
CANINTF &= 0xFD;
// Get RX buffer
MCP2515_ReadRXbuffer1();
SetEvent(MCP2515_DRV_ID,CAN_RCV_MSG);
}
if ( CANINTF & 0x04) // TXB0 full
MCP2515_BitModify(CAN2510_REG_CANINTF, 0x04, 0x00);
if ( CANINTF & 0x08) // TXB1 full
MCP2515_BitModify(CAN2510_REG_CANINTF, 0x08, 0x00);
if ( CANINTF & 0x10) // TXB2 full
MCP2515_BitModify(CAN2510_REG_CANINTF, 0x10, 0x00);
if ( CANINTF & 0x20) // Error
MCP2515_BitModify(CAN2510_REG_CANINTF, 0x20, 0x00);
if ( CANINTF & 0x40) // WAKEIF
MCP2515_BitModify(CAN2510_REG_CANINTF, 0x40, 0x00);
if ( CANINTF & 0x80) // message error
MCP2515_BitModify(CAN2510_REG_CANINTF, 0x80, 0x00);
}
}
} void MCP2515_Init(void)
{
// define the CS pin
// See the drv_spi.h and set the correct value
SPI_MCP2515.CS_address = (ram char*)&MCP2515_CS_PORT;
SPI_MCP2515.CS_bit = MCP2515_CS_BIT; // ID of the calling task
GetTaskID (&SPI_MCP2515.CallerID); // Enable INT1 for MCP2515 interrupt
ADCON1 = 0x0F;
INTCON3bits.INT1IP = ;
INTCON2bits.INTEDG1 = ;
INTCON3bits.INT1IF = ;
INTCON3bits.INT1IE = ; MCP2515_Reset();
return;
} void MCP2515_Config(void)
{
// First: enter in configuration mode
MCP2515_BitModify(CAN2510_REG_CANCTRL, 0xE0, 0x80);
MCP2515_GetStatus();
if ( (CANSTAT & 0xE0) != 0x80)
{
Nop(); // config error !
} // bit timing configuration 125khz Q=10Mhz
CNF1 = 0x41; // Synchro = 1 Tq et BRP = 1
MCP2515_ByteWrite(CAN2510_REG_CNF1, CNF1);
CNF2 = 0xac;
MCP2515_ByteWrite(CAN2510_REG_CNF2, CNF2);
CNF3 = 0x07;
MCP2515_ByteWrite(CAN2510_REG_CNF3, CNF3); TXRTSCTRL = 0x00; // No IT pin or RTS pin
MCP2515_ByteWrite(CAN2510_REG_TXRTSCTRL, TXRTSCTRL);
// No filter and mask for this release CANINTE = 0xE3; // All interrupts enable without TX
MCP2515_ByteWrite(CAN2510_REG_CANINTE, CANINTE);
CANINTF = 0x00; // Clear interrupt flags
MCP2515_ByteWrite(CAN2510_REG_CANINTF, CANINTF); #ifdef __LOOPBACK__
MCP2515_BitModify(CAN2510_REG_CANCTRL, 0xE0, 0x40);
#else
MCP2515_BitModify(CAN2510_REG_CANCTRL, 0xE0, 0x00);
#endif // Test
MCP2515_ByteRead(CAN2510_REG_RXB0CTRL, &RXB0CTRL); /* Init the different FIFO */
CAN_current_message = NULL;
CAN_list_head = NULL;
CAN_list_head_rcv = NULL; return;
} void MCP2515_Reset(void)
{
mcp2515_cmd[] = CAN2510_CMD_RESET;
// Address of the raw data to send
SPI_MCP2515.SDO_ram_data = &mcp2515_cmd[];
SPI_MCP2515.SDO_num_bytes = ;
SPI_MCP2515.SDI_num_bytes = ;
// Place the message in the SPI driver queue
SPI_enqMsg(&SPI_MCP2515);
SetEvent(SPI_DRV_ID, SPI_NEW_MSG);
// Wait for the end of operation
WaitEvent(SPI_QUEUE_EMPTY);
ClearEvent(SPI_QUEUE_EMPTY);
} void MCP2515_GetStatus(void)
{
mcp2515_cmd[] = CAN2510_CMD_READ;
mcp2515_cmd[] = CAN2510_REG_CANSTAT;
// It is not necessary to send instruction
// Address of the raw data to send
SPI_MCP2515.SDO_ram_data = &mcp2515_cmd[];
// Length of the message to send ( 0 = no SDO)
SPI_MCP2515.SDO_num_bytes = ; // Address of the raw data to receive
SPI_MCP2515.SDI_ram_data = &CANSTAT;
SPI_MCP2515.SDI_num_bytes = ;
//SPI_MCP2515.instruction = CAN2510_CMD_READ; // Place the message in the SPI driver queue
SPI_enqMsg(&SPI_MCP2515);
SetEvent(SPI_DRV_ID, SPI_NEW_MSG);
// Wait for the end of operation
WaitEvent(SPI_QUEUE_EMPTY);
ClearEvent(SPI_QUEUE_EMPTY);
} void MCP2515_BitModify(unsigned char addr, unsigned char mask, unsigned char data)
{
mcp2515_cmd[] = CAN2510_CMD_BITMOD;
mcp2515_cmd[] = addr;
mcp2515_cmd[] = mask;
mcp2515_cmd[] = data; // It is not necessary to send instruction
// Address of the raw data to send
SPI_MCP2515.SDO_ram_data = &mcp2515_cmd[];
// Length of the message to send ( 0 = no SDO)
SPI_MCP2515.SDO_num_bytes = ; SPI_MCP2515.SDI_num_bytes = ; // Place the message in the SPI driver queue
SPI_enqMsg(&SPI_MCP2515);
SetEvent(SPI_DRV_ID, SPI_NEW_MSG);
// Wait for the end of operation
WaitEvent(SPI_QUEUE_EMPTY);
ClearEvent(SPI_QUEUE_EMPTY);
} void MCP2515_ByteWrite(unsigned char addr, unsigned char data)
{
mcp2515_cmd[] = CAN2510_CMD_WRITE;
mcp2515_cmd[] = addr;
mcp2515_cmd[] = data; // Address of the raw data to send
SPI_MCP2515.SDO_ram_data = &mcp2515_cmd[];
// Length of the message to send ( 0 = no SDO)
SPI_MCP2515.SDO_num_bytes = ;
SPI_MCP2515.SDI_num_bytes = ; // Place the message in the SPI driver queue
SPI_enqMsg(&SPI_MCP2515);
SetEvent(SPI_DRV_ID, SPI_NEW_MSG);
// Wait for the end of operation
WaitEvent(SPI_QUEUE_EMPTY);
ClearEvent(SPI_QUEUE_EMPTY);
} void MCP2515_ByteRead(unsigned char addr, unsigned char* pdata)
{
mcp2515_cmd[] = CAN2510_CMD_READ;
mcp2515_cmd[] = addr; // Address of the raw data to send
SPI_MCP2515.SDO_ram_data = &mcp2515_cmd[];
// Length of the message to send ( 0 = no SDO)
SPI_MCP2515.SDO_num_bytes = ;
SPI_MCP2515.SDI_ram_data = pdata;
SPI_MCP2515.SDI_num_bytes = ; // Place the message in the SPI driver queue
SPI_enqMsg(&SPI_MCP2515);
SetEvent(SPI_DRV_ID, SPI_NEW_MSG);
// Wait for the end of operation
WaitEvent(SPI_QUEUE_EMPTY);
ClearEvent(SPI_QUEUE_EMPTY);
} void MCP2515_RTS(unsigned char buffer_TX)
{
mcp2515_cmd[] = CAN2510_CMD_RTS | buffer_TX; // Address of the raw data to send
SPI_MCP2515.SDO_ram_data = &mcp2515_cmd[];
// Length of the message to send ( 0 = no SDO)
SPI_MCP2515.SDO_num_bytes = ;
SPI_MCP2515.SDI_num_bytes = ; // Place the message in the SPI driver queue
SPI_enqMsg(&SPI_MCP2515);
SetEvent(SPI_DRV_ID, SPI_NEW_MSG);
// Wait for the end of operation
WaitEvent(SPI_QUEUE_EMPTY);
ClearEvent(SPI_QUEUE_EMPTY);
} void MCP2515_LoadTXbuffer0(void)
{
unsigned char i;
unsigned char *pst; pst = (unsigned char*)&TXB0;
mcp2515_cmd[] = 0x40; // TXB0 0x31
for (i=;i<;i++)
{
mcp2515_cmd[i]= *pst;
pst++;
} // Length of the message to send ( 0 = no SDO)
SPI_MCP2515.SDO_ram_data = &mcp2515_cmd[];
SPI_MCP2515.SDO_num_bytes = ;
SPI_MCP2515.SDI_num_bytes = ; // Place the message in the SPI driver queue
SPI_enqMsg(&SPI_MCP2515);
SetEvent(SPI_DRV_ID, SPI_NEW_MSG);
// Wait for the end of operation
WaitEvent(SPI_QUEUE_EMPTY);
ClearEvent(SPI_QUEUE_EMPTY);
} void MCP2515_ReadRXbuffer0(void)
{
mcp2515_cmd[] = 0x90; // Adress -> 0x61
SPI_MCP2515.SDO_ram_data = &mcp2515_cmd[];
// Length of the message to send ( 0 = no SDO)
SPI_MCP2515.SDO_num_bytes = ; // Address of the raw data to receive
SPI_MCP2515.SDI_ram_data = (unsigned char*)&RXB0;
SPI_MCP2515.SDI_num_bytes = ; // Place the message in the SPI driver queue
SPI_enqMsg(&SPI_MCP2515);
SetEvent(SPI_DRV_ID, SPI_NEW_MSG);
// Wait for the end of operation
WaitEvent(SPI_QUEUE_EMPTY);
ClearEvent(SPI_QUEUE_EMPTY);
} void MCP2515_ReadRXbuffer1(void)
{
mcp2515_cmd[] = 0x94; // Adress -> 0x71
SPI_MCP2515.SDO_ram_data = &mcp2515_cmd[];
// Length of the message to send ( 0 = no SDO)
SPI_MCP2515.SDO_num_bytes = ; // Address of the raw data to receive
SPI_MCP2515.SDI_ram_data = (unsigned char*)&RXB0;
SPI_MCP2515.SDI_num_bytes = ; // Place the message in the SPI driver queue
SPI_enqMsg(&SPI_MCP2515);
SetEvent(SPI_DRV_ID, SPI_NEW_MSG);
// Wait for the end of operation
WaitEvent(SPI_QUEUE_EMPTY);
ClearEvent(SPI_QUEUE_EMPTY);
} /**********************************************************************
* Parse the entier TX message list to find any message to transfer.
* Once a such message is found we post an event to the sending task
* to tell the transfer is started and we break.
* The event is used if the task want to send as fast as possible a
* set of message. Doing so the task will be able to send a new message
* every time a TASK_CAN_TX_EVENT event is received.
*
* @param type IN Number of the hardware buffer
* @return Status E_OK if tranfer initiated
* E_OS_STATE otherwise
**********************************************************************/
StatusType CopyFrameBuffer2Hard(void)
{
StatusType returned_type;
unsigned char foo;
returned_type = E_OS_STATE; CAN_current_message = CAN_deqMsg(); if (CAN_current_message == NULL)
return(returned_type); #ifdef __EXT29BITS__
TXB0.TXBnEID0 = CAN_current_message->CANID;
TXB0.TXBnEID8 = CAN_current_message->CANID >> ;
TXB0.TXBnSIDL = (CAN_current_message->CANID >> ) & 0x03;
foo = (CAN_current_message->CANID >> ) & 0xE0;
foo = foo | 0x08;
TXB0.TXBnSIDL = TXB0.TXBnSIDL + foo;
TXB0.TXBnSIDH = CAN_current_message->CANID >> ;
#else
#ifdef __STD11BITS__
TXB0.TXBnSIDL = CAN_current_message->CANID << ;
TXB0.TXBnSIDH = CAN_current_message->CANID >> ;
#else
#error "you should define 11 or 29 bits for CANID !"
#endif
#endif
TXB0.TXBnDLC = CAN_current_message->length & 0x0F;
TXB0.TXBnD0 = CAN_current_message->data[];
TXB0.TXBnD1 = CAN_current_message->data[];
TXB0.TXBnD2 = CAN_current_message->data[];
TXB0.TXBnD3 = CAN_current_message->data[];
TXB0.TXBnD4 = CAN_current_message->data[];
TXB0.TXBnD5 = CAN_current_message->data[];
TXB0.TXBnD6 = CAN_current_message->data[];
TXB0.TXBnD7 = CAN_current_message->data[];
CAN_current_message->state = CAN_MSG_SENT; // MCP2551 TX_buffer0 update
MCP2515_LoadTXbuffer0(); // Send the buffer0 transmit command
MCP2515_RTS(0x01); // 1st buffer -> buffer0 SetEvent(CAN_current_message->CallerID, CAN_QUEUE_EMPTY);
//RXB0CONbits.RXRTRRO = 1;
returned_type = E_OK; return(returned_type);
} /**********************************************************************
* Enqueue a client packet object into the RS task queue.
*
* Once placed in queue, client must not modify the data
* otherwise unpredictable results. To safely change the object,
* dequeue, modify, re-enqueue.
*
* The code in mainly executed in critical region [SuspendAllInterrupt]
* because many tasks can call this function at the same time and break
* the FIFO list.
*
* Returns 1 if successfull, 0 if message could not be enqueued
**********************************************************************/
StatusType CAN_enqMsg(CAN_message_tRef toEnqueue)
{
CAN_message_tRef CAN_list_itor; if (toEnqueue != NULL)
{
SuspendOSInterrupts();
if (CAN_list_head == NULL)
CAN_list_head = toEnqueue;
else
{
CAN_list_itor = CAN_list_head;
while (CAN_list_itor->next != NULL)
CAN_list_itor = CAN_list_itor->next;
CAN_list_itor->next = toEnqueue;
}
toEnqueue->next = NULL;
toEnqueue->CallerID = id_tsk_run;
toEnqueue->state = CAN_FULL;
CAN_list_count++;
ResumeOSInterrupts();
return E_OK;
}
else
return E_OS_STATE;
} /**********************************************************************
* Dequeue a client message from the RS task queue.
*
*
*********************************************************************/
CAN_message_tRef CAN_deqMsg(void)
{
CAN_message_tRef CAN_list_itor; SuspendOSInterrupts();
CAN_list_itor = NULL;
if (CAN_list_head != NULL)
{
CAN_list_itor = CAN_list_head;
CAN_list_head = CAN_list_head->next;
CAN_list_count--;
}
ResumeOSInterrupts();
return CAN_list_itor;
} /**********************************************************************
* Enqueue a client packet object into the RS task queue.
*
* Once placed in queue, client must not modify the data
* otherwise unpredictable results. To safely change the object,
* dequeue, modify, re-enqueue.
*
* The code in mainly executed in critical region [SuspendAllInterrupt]
* because many tasks can call this function at the same time and break
* the FIFO list.
*
* Returns 1 if successfull, 0 if message could not be enqueued
**********************************************************************/
StatusType CAN_RCV_Register(CAN_message_tRef toEnqueue)
{
CAN_message_tRef CAN_list_itor; if (toEnqueue != NULL)
{
SuspendOSInterrupts();
if (CAN_list_head_rcv == NULL)
CAN_list_head_rcv = toEnqueue;
else
{
CAN_list_itor = CAN_list_head_rcv;
while (CAN_list_itor->next != NULL)
CAN_list_itor = CAN_list_itor->next;
CAN_list_itor->next = toEnqueue;
}
toEnqueue->next = NULL;
toEnqueue->CallerID = id_tsk_run;
CAN_list_count_rcv++;
ResumeOSInterrupts();
return E_OK;
}
else
return E_OS_STATE;
} /**********************************************************************
* Parse the entier RX message list to find any task waiting for the
* received message ID.
* Once a such taks is found we post an event to the waiting task
* to tell its software buffer is full and we break.
* The event is used if the task want to wait for a particular message
* ID without overloading the CPU by a pooling method.
*
* @param type IN Number of the hardware buffer
* @return Status E_OK if tranfer initiated
* E_OS_STATE otherwise
**********************************************************************/
StatusType CopyHard2FrameBuffer(void)
{
StatusType returned_type;
unsigned long ID_received;
CAN_message_tRef CAN_list_itor; returned_type = E_OK; if (CAN_list_head_rcv != NULL)
{
CAN_list_itor = CAN_list_head_rcv;
do
{
#ifdef __NOFILTER__
if ()
#else
#ifdef __EXT29BITS__
ID_received = ;
ID_received += (unsigned long)(RXB0.RXBnEID0);
ID_received += (unsigned long)(RXB0.RXBnEID8) << ;
ID_received += (unsigned long)(RXB0.RXBnSIDL & 0x03) << ;
ID_received += (unsigned long)(RXB0.RXBnSIDL & 0xE0) << ;
ID_received += (unsigned long)(RXB0.RXBnSIDH & 0xFF) << ;
#else
#ifdef __STD11BITS__
ID_received = ;
ID_received += (unsigned long)(RXB0.RXBnSIDL) >> ;
ID_received += (unsigned long)(RXB0.RXBnSIDH) << ;
#else
#error "you should define 11 or 29 bits for CANID !"
#endif
#endif
if (CAN_list_itor->CANID == ID_received)
#endif
{
if (CAN_list_itor->state == CAN_FREE)
{
CAN_list_itor->data[] = RXB0.RXBnD0;
CAN_list_itor->data[] = RXB0.RXBnD1;
CAN_list_itor->data[] = RXB0.RXBnD2;
CAN_list_itor->data[] = RXB0.RXBnD3;
CAN_list_itor->data[] = RXB0.RXBnD4;
CAN_list_itor->data[] = RXB0.RXBnD5;
CAN_list_itor->data[] = RXB0.RXBnD6;
CAN_list_itor->data[] = RXB0.RXBnD7;
CAN_list_itor->length = RXB0.RXBnDLC & 0x0F;
CAN_list_itor->state = CAN_FULL;
SetEvent(CAN_list_itor->CallerID, CAN_QUEUE_FULL);
}
else
returned_type = E_OS_STATE;
}
CAN_list_itor = CAN_list_itor->next;
}
while (CAN_list_itor != NULL);
} return(returned_type);
} /**********************************************************************
* ISR of the CAN driver.
*
* For each interrupt we disable the IE first to avoid any infinite loop
* and we clear the IF in the dedicated function (Read or Write CAN mess).
* Indeed we have to clear the IT when the message has been properly
* accessed and is no more used. The IF lets the peripheral accept a new
* message.
* If 3 frames arrive at the same time, the two first are stored in the
* RCV buffers and the third is discarded (temporary overload bus).
*
* @return void
**********************************************************************/
void MCP2551_INT(void)
{
INTCON3bits.INT1IF = ;
// Send a request to the driver
SetEvent(MCP2515_DRV_ID,MCP2515_IRQ_REQUEST);
} /* End of File : drv_mcp2515.c */
/**********************************************************************/
/* */
/* File name: drv_mcp2515.h */
/* */
/* Since: 2005-Nov-30 */
/* */
/* Version: PICos18 v2.04 */
/* Copyright (C) 2003, 2004, 2005 Pragmatec. */
/* MCP2515 CAN driver v1.00 */
/* */
/* Author: Designed by Pragmatec S.A.R.L. www.pragmatec.net */
/* ROZIER Bertrand [RZR] bertrand.rozier@pragmatec.net*/
/* */
/* Purpose: MCP2515 : SPI CAN controller management. */
/* It allows task to send data at the same time through a */
/* dedicated FIFO, and to wait for a certain CAN frame. */
/* */
/* Distribution: This file is part of PICos18. */
/* PICos18 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, or (at your option) */
/* any later version. */
/* */
/* PICos18 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 gpsim; see the file */
/* COPYING.txt. If not, write to the Free Software */
/* Foundation, 59 Temple Place - Suite 330, */
/* Boston, MA 02111-1307, USA. */
/* */
/* > A special exception to the GPL can be applied should */
/* you wish to distribute a combined work that includes */
/* PICos18, without being obliged to provide the source */
/* code for any proprietary components. */
/* */
/* History: */
/* 2005/11/30 [RZR] Create this file. */
/* */
/**********************************************************************/ #ifndef _MCP2515_DRV_H_
#define _MCP2515_DRV_H_ #include "pro_man.h"
#include "even_man.h"
#include "alarm.h" /*****************************************************
* Definition dedicated to the local functions.
****************************************************/
#define CAN_MSG_SENT 0x02
#define CAN_FREE 0x00
#define CAN_FULL 0x01
#define CAN_EMPTY 0x00
#define TRUE 0x01
#define FALSE 0x00
#define TX_MESSAGE 0x01
#define RX_MESSAGE 0x00 #define TXB0_REG 0x30
#define TXB1_REG 0x40
#define TXB2_REG 0x50
#define RXB0_REG 0x60
#define RXB1_REG 0x70 struct _CAN_frame {
unsigned long CANID;
unsigned char length;
unsigned char data[];
unsigned char CallerID;
unsigned char state;
struct _CAN_frame *next;
};
typedef struct _CAN_frame CAN_message_t, *CAN_message_tRef; struct _TX_buffer {
// unsigned char TXBnCTRL;
unsigned char TXBnSIDH;
unsigned char TXBnSIDL;
unsigned char TXBnEID8;
unsigned char TXBnEID0;
unsigned char TXBnDLC;
unsigned char TXBnD0;
unsigned char TXBnD1;
unsigned char TXBnD2;
unsigned char TXBnD3;
unsigned char TXBnD4;
unsigned char TXBnD5;
unsigned char TXBnD6;
unsigned char TXBnD7;
};
typedef struct _TX_buffer TXBn_t, *TXBn_tRef; struct _RX_buffer {
// unsigned char RXBnCTRL;
unsigned char RXBnSIDH; //0x61
unsigned char RXBnSIDL;
unsigned char RXBnEID8;
unsigned char RXBnEID0;
unsigned char RXBnDLC;
unsigned char RXBnD0;
unsigned char RXBnD1;
unsigned char RXBnD2;
unsigned char RXBnD3;
unsigned char RXBnD4;
unsigned char RXBnD5;
unsigned char RXBnD6;
unsigned char RXBnD7; };
typedef struct _RX_buffer RXBn_t, *RXBn_tRef; #define CAN_freeMsg(x) x.state = CAN_FREE; StatusType CAN_enqMsg(CAN_message_tRef toEnqueue);
CAN_message_tRef CAN_deqMsg(void);
StatusType CopyHard2FrameBuffer(void);
StatusType CopyFrameBuffer2Hard(void);
StatusType CAN_RCV_Register(CAN_message_tRef toEnqueue);
void CAN_config(void); // CAN configuration registers
#define CAN2510_REG_BFPCTRL 0x0C
#define CAN2510_REG_TXRTSCTRL 0x0D
#define CAN2510_REG_CANSTAT 0x0E // Repeated every 16 locations (1E, 2E, ...)
#define CAN2510_REG_CANCTRL 0x0F // Repeated every 16 locations (1F, 2F, ...) #define CAN2510_REG_TEC 0x1C
#define CAN2510_REG_REC 0x1D #define CAN2510_REG_CNF3 0x28
#define CAN2510_REG_CNF2 0x29
#define CAN2510_REG_CNF1 0x2A
#define CAN2510_REG_CANINTE 0x2B
#define CAN2510_REG_CANINTF 0x2C
#define CAN2510_REG_EFLG 0x2D // CAN Receive Mask/Filter registers
#define CAN2510_REG_RXM0SIDH 0x20
#define CAN2510_REG_RXM0SIDL 0x21
#define CAN2510_REG_RXM0EID8 0x22
#define CAN2510_REG_RXM0EID0 0x23
#define CAN2510_REG_RXM1SIDH 0x24
#define CAN2510_REG_RXM1SIDL 0x25
#define CAN2510_REG_RXM1EID8 0x26
#define CAN2510_REG_RXM1EID0 0x27
#define CAN2510_REG_RXF0SIDH 0x00
#define CAN2510_REG_RXF0SIDL 0x01
#define CAN2510_REG_RXF0EID8 0x02
#define CAN2510_REG_RXF0EID0 0x03
#define CAN2510_REG_RXF1SIDH 0x04
#define CAN2510_REG_RXF1SIDL 0x05
#define CAN2510_REG_RXF1EID8 0x06
#define CAN2510_REG_RXF1EID0 0x07
#define CAN2510_REG_RXF2SIDH 0x08
#define CAN2510_REG_RXF2SIDL 0x09
#define CAN2510_REG_RXF2EID8 0x0A
#define CAN2510_REG_RXF2EID0 0x0B
#define CAN2510_REG_RXF3SIDH 0x10
#define CAN2510_REG_RXF3SIDL 0x11
#define CAN2510_REG_RXF3EID8 0x12
#define CAN2510_REG_RXF3EID0 0x13
#define CAN2510_REG_RXF4SIDH 0x14
#define CAN2510_REG_RXF4SIDL 0x15
#define CAN2510_REG_RXF4EID8 0x16
#define CAN2510_REG_RXF4EID0 0x17
#define CAN2510_REG_RXF5SIDH 0x18
#define CAN2510_REG_RXF5SIDL 0x19
#define CAN2510_REG_RXF5EID8 0x1A
#define CAN2510_REG_RXF5EID0 0x1B // CAN Transmit Control/Header/Data registers
#define CAN2510_REG_TXB0CTRL 0x30
#define CAN2510_REG_TXB0SIDH 0x31
#define CAN2510_REG_TXB0SIDL 0x32
#define CAN2510_REG_TXB0EID8 0x33
#define CAN2510_REG_TXB0EID0 0x34
#define CAN2510_REG_TXB0DLC 0x35
#define CAN2510_REG_TXB0D0 0x36
#define CAN2510_REG_TXB0D1 0x37
#define CAN2510_REG_TXB0D2 0x38
#define CAN2510_REG_TXB0D3 0x39
#define CAN2510_REG_TXB0D4 0x3A
#define CAN2510_REG_TXB0D5 0x3B
#define CAN2510_REG_TXB0D6 0x3C
#define CAN2510_REG_TXB0D7 0x3D #define CAN2510_REG_TXB1CTRL 0x40
#define CAN2510_REG_TXB1SIDH 0x41
#define CAN2510_REG_TXB1SIDL 0x42
#define CAN2510_REG_TXB1EID8 0x43
#define CAN2510_REG_TXB1EID0 0x44
#define CAN2510_REG_TXB1DLC 0x45
#define CAN2510_REG_TXB1D0 0x46
#define CAN2510_REG_TXB1D1 0x47
#define CAN2510_REG_TXB1D2 0x48
#define CAN2510_REG_TXB1D3 0x49
#define CAN2510_REG_TXB1D4 0x4A
#define CAN2510_REG_TXB1D5 0x4B
#define CAN2510_REG_TXB1D6 0x4C
#define CAN2510_REG_TXB1D7 0x4D #define CAN2510_REG_TXB2CTRL 0x50
#define CAN2510_REG_TXB2SIDH 0x51
#define CAN2510_REG_TXB2SIDL 0x52
#define CAN2510_REG_TXB2EID8 0x53
#define CAN2510_REG_TXB2EID0 0x54
#define CAN2510_REG_TXB2DLC 0x55
#define CAN2510_REG_TXB2D0 0x56
#define CAN2510_REG_TXB2D1 0x57
#define CAN2510_REG_TXB2D2 0x58
#define CAN2510_REG_TXB2D3 0x59
#define CAN2510_REG_TXB2D4 0x5A
#define CAN2510_REG_TXB2D5 0x5B
#define CAN2510_REG_TXB2D6 0x5C
#define CAN2510_REG_TXB2D7 0x5D // CAN Transmit Control/Header/Data registers
#define CAN2510_REG_RXB0CTRL 0x60
#define CAN2510_REG_RXB0SIDH 0x61
#define CAN2510_REG_RXB0SIDL 0x62
#define CAN2510_REG_RXB0EID8 0x63
#define CAN2510_REG_RXB0EID0 0x64
#define CAN2510_REG_RXB0DLC 0x65
#define CAN2510_REG_RXB0D0 0x66
#define CAN2510_REG_RXB0D1 0x67
#define CAN2510_REG_RXB0D2 0x68
#define CAN2510_REG_RXB0D3 0x69
#define CAN2510_REG_RXB0D4 0x6A
#define CAN2510_REG_RXB0D5 0x6B
#define CAN2510_REG_RXB0D6 0x6C
#define CAN2510_REG_RXB0D7 0x6D #define CAN2510_REG_RXB1CTRL 0x70
#define CAN2510_REG_RXB1SIDH 0x71
#define CAN2510_REG_RXB1SIDL 0x72
#define CAN2510_REG_RXB1EID8 0x73
#define CAN2510_REG_RXB1EID0 0x74
#define CAN2510_REG_RXB1DLC 0x75
#define CAN2510_REG_RXB1D0 0x76
#define CAN2510_REG_RXB1D1 0x77
#define CAN2510_REG_RXB1D2 0x78
#define CAN2510_REG_RXB1D3 0x79
#define CAN2510_REG_RXB1D4 0x7A
#define CAN2510_REG_RXB1D5 0x7B
#define CAN2510_REG_RXB1D6 0x7C
#define CAN2510_REG_RXB1D7 0x7D #define CAN2510_CMD_RESET 0xC0
#define CAN2510_CMD_WRITE 0x02
#define CAN2510_CMD_READ 0x03
#define CAN2510_CMD_RTS 0x80
#define CAN2510_CMD_BITMOD 0x05
#define CAN2510_CMD_STATUS 0xA0 // Define for RTS ( Request to send)
#define TX_B0 0x01
#define TX_B1 0x02
#define TX_B2 0x04 #endif /* _MCP2515_DRV_H_ */ /* End of File : drv_mcp2515.h */

最新文章

  1. win10连vpn
  2. C语言隐形密码输入
  3. test3
  4. Android ADT 下载 ( ADT-23.0.7 )
  5. Xcode中使用GitHub详解
  6. 使用BSD socket编写Windows版的网络程序
  7. 腾讯QQ、新浪微博等知名社交网络图标素材
  8. POJ3750
  9. Ubuntu Eclipse的Tomcat小问题:不能输入server name,不能启动tomcat
  10. hdu3873 有约束条件的最短路
  11. POPTEST老李谈Debug和Release的区别(c#) 1
  12. Python简要学习笔记
  13. 使用ui-route实现多层嵌套路由
  14. 中国科学技术大学统一身份认证系统CAS
  15. hdu1875(最小生成树prime)
  16. flume常见异常汇总以及解决方案
  17. 014 Security的认证流程源码级详解
  18. There is a chart instance already initialized on the dom!警告
  19. matlab学习(4) any 和cellfun用法
  20. 转apk打包

热门文章

  1. TF-搞不懂的TF矩阵加法
  2. (转载)使用SQL-Server创建一个银行数据管理系统Ⅰ
  3. C#比较时分秒大小,终止分钟默认加十分钟,解决跨天、跨月、跨年的情况
  4. 自定义排序及Hadoop序列化
  5. hdoj1203 I NEED A OFFER!(DP,01背包)
  6. 牛客网 桂林电子科技大学第三届ACM程序设计竞赛 C.二元-K个二元组最小值和最大-优先队列+贪心(思维)
  7. Hadoop整理二(Hadoop分布式存储系统HDFS)
  8. Java—集合工具类
  9. 新一代数据库TiDB在美团的实践
  10. java UTF8 HEX