📄 can_hw.c
字号:
/*----------------------------------------------------------------------------
* R T L - C A N D r i v e r
*----------------------------------------------------------------------------
* Name: CAN_Hw.c
* Purpose: CAN Driver, Hardware specific module for LPC2xxx
* Rev.: V3.12
*----------------------------------------------------------------------------
* This code is part of the RealView Run-Time Library.
* Copyright (c) 2004-2007 KEIL - An ARM Company. All rights reserved.
*---------------------------------------------------------------------------*/
#include <RTL.h> /* RTX kernel functions & defines */
#include <LPC23xx.h> /* LPC23xx definitions */
#include "RTX_CAN.h" /* CAN Generic functions & defines */
#include "CAN_hw.h" /* CAN hw specific functions & defines */
#include "CAN_reg.h" /* LPC2xxx CAN registers */
#pragma diag_suppress 550
/* Values of bit time register for different baudrates
NT = Nominal bit time = TSEG1 + TSEG2 + 3
SP = Sample point = ((TSEG2 +1) / (TSEG1 + TSEG2 + 3)) * 100%
SAM, SJW, TSEG1, TSEG2, NT, SP */
const U32 CAN_BIT_TIME[] = { 0, /* not used */
0, /* not used */
0, /* not used */
0, /* not used */
0x0001C000, /* 0+1, 3+1, 1+1, 0+1, 4, 75% */
0, /* not used */
0x0012C000, /* 0+1, 3+1, 2+1, 1+1, 6, 67% */
0, /* not used */
0x0023C000, /* 0+1, 3+1, 3+1, 2+1, 8, 63% */
0, /* not used */
0x0025C000, /* 0+1, 3+1, 5+1, 2+1, 10, 70% */
0, /* not used */
0x0036C000, /* 0+1, 3+1, 6+1, 3+1, 12, 67% */
0, /* not used */
0, /* not used */
0x0048C000, /* 0+1, 3+1, 8+1, 4+1, 15, 67% */
0x0049C000, /* 0+1, 3+1, 9+1, 4+1, 16, 69% */
};
/*----------------------------------------------------------------------------
* CAN RTX Hardware Specific Driver Functions for LPC2xxx
*----------------------------------------------------------------------------
* Functions implemented in this module:
* static CAN_ERROR CAN_hw_set_baudrate (U32 ctrl, U32 baudrate)
* CAN_ERROR CAN_hw_setup (U32 ctrl)
* CAN_ERROR CAN_hw_init (U32 ctrl, U32 baudrate)
* CAN_ERROR CAN_hw_start (U32 ctrl)
* CAN_ERROR CAN_hw_tx_empty (U32 ctrl)
* CAN_ERROR CAN_hw_wr (U32 ctrl, CAN_msg *msg)
* static void CAN_hw_rd (U32 ctrl, CAN_msg *msg)
* CAN_ERROR CAN_hw_set (U32 ctrl, CAN_msg *msg)
* CAN_ERROR CAN_hw_rx_object (U32 ctrl, U32 ch, U32 id, CAN_FORMAT format)
* CAN_ERROR CAN_hw_tx_object (U32 ctrl, U32 ch, CAN_FORMAT format)
* Interrupt fuctions
*---------------------------------------------------------------------------*/
/* Static functions used only in this module */
static void CAN_hw_rd (U32 ctrl, CAN_msg *msg);
#if (USE_CAN_CTRL1 == 1) || (USE_CAN_CTRL2 == 1)
static void CAN_ISR (void) __irq;
#endif
/************************* Auxiliary Functions *******************************/
/*------------------------ CAN_hw_set_baudrate ------------------------------
*
* Setup the requested baudrate
*
* Parameter: ctrl: Index of the hardware CAN controller (1 .. x)
* baudrate: Baudrate
*
* Return: CAN_ERROR: Error code
*---------------------------------------------------------------------------*/
static CAN_ERROR CAN_hw_set_baudrate (U32 ctrl, U32 baudrate) {
U32 ctrl0 = ctrl-1; /* Controller index 0 .. x-1 */
regCAN *ptrcan = (regCAN *) CAN_BASE[ctrl0];
U32 result = 0;
U32 nominal_time;
/* Determine which nominal time to use for PCLK and baudrate */
if (baudrate <= 500000) {
nominal_time = 12;
} else if (((PCLK / 1000000) % 15) == 0) {
nominal_time = 15;
} else if (((PCLK / 1000000) % 16) == 0) {
nominal_time = 16;
} else {
nominal_time = 10;
}
/* Prepare value appropriate for bit time register */
result = (PCLK / nominal_time) / baudrate - 1;
result &= 0x000003FF;
result |= CAN_BIT_TIME[nominal_time];
ptrcan->CANBTR = result; /* Set bit timing */
return CAN_OK;
}
/*************************** Module Functions ********************************/
/*--------------------------- CAN_hw_setup ----------------------------------
*
* Setup CAN transmit and receive PINs and interrupt vectors
*
* Parameter: ctrl: Index of the hardware CAN controller (1 .. x)
*
* Return: CAN_ERROR: Error code
*---------------------------------------------------------------------------*/
CAN_ERROR CAN_hw_setup (U32 ctrl) {
switch (ctrl) {
case 1:
#if USE_CAN_CTRL1 == 1
PCONP |= 1 << 13; /* Enable clock for CAN1 */
PINSEL0 &= 0xFFFFFFF0; /* Reset CAN1 bits */
PINSEL0 |= 0x00000005; /* Set CAN1 bits to b0101 */
/* Set interrupt vector for CAN1 */
*(&VICVectAddr23) = (unsigned long) CAN_ISR;
*(&VICVectCntl23) = 1;
VICIntEnable = (1 << 23); /* Enable CAN1 Interrupt */
#endif
break;
case 2:
#if USE_CAN_CTRL2 == 1
PCONP |= 1 << 14; /* Enable clock for CAN2 */
PINSEL0 &= 0xFFFFF0FF; /* Reset CAN2 bits */
PINSEL0 |= 0x00000A00; /* Set CAN2 bits to b1010 */
/* Set interrupt vector for CAN2 */
*(&VICVectAddr23) = (unsigned long) CAN_ISR;
*(&VICVectCntl23) = 1;
VICIntEnable = (1 << 23); /* Enable CAN2 Interrupt */
#endif
break;
default:
return CAN_UNEXIST_CTRL_ERROR;
}
return CAN_OK;
}
/*--------------------------- CAN_hw_init -----------------------------------
*
* Initialize the CAN hardware
*
* Parameter: ctrl: Index of the hardware CAN controller (1 .. x)
* baudrate: Baudrate
*
* Return: CAN_ERROR: Error code
*---------------------------------------------------------------------------*/
CAN_ERROR CAN_hw_init (U32 ctrl, U32 baudrate) {
U32 ctrl0 = ctrl-1; /* Controller index 0 .. x-1 */
regCAN_AF *ptrcan_af = (regCAN_AF *) CAN_AF_BASE;
regCAN *ptrcan = (regCAN *) CAN_BASE[ctrl0];
ptrcan_af->AFMR = 2; /* By default filter is not used */
ptrcan->CANMOD = 1; /* Enter reset mode */
ptrcan->CANIER = 0; /* Disable all interrupts */
ptrcan->CANGSR = 0; /* Clear status register */
CAN_hw_set_baudrate(ctrl, baudrate);/* Set bit timing */
ptrcan->CANIER = 0x0003; /* Enable Tx and Rx interrupt */
return CAN_OK;
}
/*--------------------------- CAN_hw_start ----------------------------------
*
* Enable the CAN interrupts (recive or/and transmit)
*
* Parameter: ctrl: Index of the hardware CAN controller (1 .. x)
*
* Return: CAN_ERROR: Error code
*---------------------------------------------------------------------------*/
CAN_ERROR CAN_hw_start (U32 ctrl) {
U32 ctrl0 = ctrl-1; /* Controller index 0 .. x-1 */
regCAN *ptrcan = (regCAN *) CAN_BASE[ctrl0];
ptrcan->CANMOD = 0; /* Enter normal operating mode */
return CAN_OK;
}
/*--------------------------- CAN_hw_tx_empty -------------------------------
*
* Check if controller is available for transmission
*
* Parameter: ctrl: Index of the hardware CAN controller (1 .. x)
*
* Return: CAN_ERROR: Error code
*---------------------------------------------------------------------------*/
CAN_ERROR CAN_hw_tx_empty (U32 ctrl) {
U32 ctrl0 = ctrl-1; /* Controller index 0 .. x-1 */
regCAN *ptrcan = (regCAN *) CAN_BASE[ctrl0];
if ((os_sem_wait (wr_sem[ctrl-1], 0) != OS_R_TMO)){ /* If semaphore is free*/
if (ptrcan->CANSR & 0x00000004) /* Transmitter ready for */
/* transmission */
return CAN_OK;
else
os_sem_send(wr_sem[ctrl-1]); /* Return a token back to semaphore */
}
return CAN_TX_BUSY_ERROR;
}
/*--------------------------- CAN_hw_wr -------------------------------------
*
* Write CAN_msg to the hardware registers of the requested controller
*
* Parameter: ctrl: Index of the hardware CAN controller (1 .. x)
* msg: Pointer to CAN message to be written to hardware
*
* Return: CAN_ERROR: Error code
*---------------------------------------------------------------------------*/
CAN_ERROR CAN_hw_wr (U32 ctrl, CAN_msg *msg) {
U32 ctrl0 = ctrl-1; /* Controller index 0 .. x-1 */
U32 CANData;
regCAN *ptrcan = (regCAN *) CAN_BASE[ctrl0];
CANData = (((U32) msg->len) << 16) & 0x000F0000 |
(msg->format == EXTENDED_FORMAT ) * 0x80000000 |
(msg->type == REMOTE_FRAME) * 0x40000000;
if (ptrcan->CANSR & 0x00000004) { /* Transmit buffer 1 free */
ptrcan->CANTF1 = CANData; /* Write frame informations */
ptrcan->CANTID1 = msg->id; /* Write CAN message identifier */
ptrcan->CANTDA1 = *(U32 *) &msg->data[0]; /* Write first 4 data bytes */
ptrcan->CANTDB1 = *(U32 *) &msg->data[4]; /* Write second 4 data bytes */
//ptrcan->CANCMR = 0x31; /* Select Tx1 for Self Tx/Rx */
ptrcan->CANCMR = 0x21; /* Start transmission without loop-back*/
}
else
return CAN_TX_BUSY_ERROR;
return CAN_OK;
}
/*--------------------------- CAN_hw_rd -------------------------------------
*
* Read CAN_msg from the hardware registers of the requested controller
*
* Parameter: ctrl: Index of the hardware CAN controller (1 .. x)
* msg: Pointer where CAN message will be read
*
* Return: CAN_ERROR: Error code
*---------------------------------------------------------------------------*/
static void CAN_hw_rd (U32 ctrl, CAN_msg *msg) {
U32 ctrl0 = ctrl-1; /* Controller index 0 .. x-1 */
U32 CANData;
U32 *CANAddr;
regCAN *ptrcan = (regCAN *) CAN_BASE[ctrl0];
/* Read frame informations */
CANData = ptrcan->CANRFS;
msg->format = (CANData & 0x80000000) == 0x80000000;
msg->type = (CANData & 0x40000000) == 0x40000000;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -