📄 mcohw_lpc2.c
字号:
/**************************************************************************
MODULE: MCOHW_LPC2
CONTAINS: Driver implementation for NXP LPC2000 derivatives with
CAN interface. Compiled and Tested with Keil Tools www.keil.com
COPYRIGHT: Embedded Systems Academy, Inc. 2002-2007.
All rights reserved. www.microcanopen.com
This software was written in accordance to the guidelines at
www.esacademy.com/software/softwarestyleguide.pdf
DISCLAIM: Read and understand our disclaimer before using this code!
www.esacademy.com/disclaim.htm
LICENSE: THIS IS THE EDUCATIONAL VERSION OF MICROCANOPEN
See file license_educational.txt or
www.microcanopen.com/license_educational.txt
A commercial MicroCANopen license is available at
www.CANopenStore.com
VERSION: 3.30, ESA 30-JAN-07
$LastChangedDate: 2007-01-30 10:38:13 -0800 (Tue, 30 Jan 2007) $
$LastChangedRevision: 232 $
***************************************************************************/
#include "mcohw.h"
#include <string.h>
#include <LPC21XX.H> // LPC21XX Peripheral Registers
#define NROF_CANPORTS 1
#define FIRST_CANPORT 1
// Define CAN SFR address bases
#define CAN_REG_BASE (0xE0000000)
#define ACCEPTANCE_FILTER_RAM_BASE (CAN_REG_BASE + 0x00038000)
#define ACCEPTANCE_FILTER_REGISTER_BASE (CAN_REG_BASE + 0x0003C000)
#define CENTRAL_CAN_REGISTER_BASE (CAN_REG_BASE + 0x00040000)
#define CAN_1_BASE (CAN_REG_BASE + 0x00044000)
#define CAN_2_BASE (CAN_REG_BASE + 0x00048000)
// Common CAN bit rates
#define CANBitrate125k_12MHz 0x001C001D
#define CANBitrate250k_12MHz 0x001C000E
// Maximum number of FullCAN Filters
#define MAX_FILTERS 32
// Size of transmit queue, must be 8, 16, 32 or 64
#define TXQUEUESIZE 16
// Timer Interrupt
void MCOHW_TimerISR (void) __attribute__ ((interrupt));
// CAN Interrupt
void MCOHW_CANISR_Err (void) __attribute__ ((interrupt));
void MCOHW_CANISR_Rx1 (void) __attribute__ ((interrupt));
void MCOHW_CANISR_Tx1 (void) __attribute__ ((interrupt));
void MCOHW_DefaultISR (void) __attribute__ ((interrupt));
/**************************************************************************
GLOBAL VARIABLES
***************************************************************************/
// Global timer/conter variable, incremented every millisecond
UNSIGNED16 volatile gTimCnt = 0;
#if (NROF_CANPORTS == 1)
// Only use this section for single CAN port implementations
// Timer is always handled by this module
#if (FIRST_CANPORT != 1)
#error "FIRST_CANPORT must be 1 for this implementation!"
#endif
// Counts number of filters (CAN message objects) used
UNSIGNED16 volatile gCANFilter = 0;
// Type definition to hold a FullCAN message
typedef struct
{
UNSIGNED32 Dat1;
UNSIGNED32 DatA;
UNSIGNED32 DatB;
} FULLCAN_MSGFIELD;
// FullCAN Message List
FULLCAN_MSGFIELD volatile gFullCANList[MAX_FILTERS];
// Lookup table for receive filters
UNSIGNED16 gFilterList[20];
// Transmit SW queue
CAN_MSG mTxQueue[TXQUEUESIZE];
UNSIGNED8 mTxIn;
UNSIGNED8 mTxOut;
// status
UNSIGNED8 mStatus = 0;
/**************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
/**************************************************************************
DOES: This function returns the global status variable.
CHANGES: The status can be changed anytime by this module, for example from
within an interrupt service routine or by any of the other
functions in this module.
BITS: 0: INIT - set to 1 after a completed initialization
left 0 if not yet inited or init failed
1: CERR - set to 1 if a CAN bit or frame error occured
2: ERPA - set to 1 if a CAN "error passive" occured
3: RXOR - set to 1 if a receive queue overrun occured
4: TXOR - set to 1 if a transmit queue overrun occured
5: Reserved
6: TXBSY - set to 1 if Transmit queue is not empty
7: BOFF - set to 1 if a CAN "bus off" error occured
**************************************************************************/
UNSIGNED8 MCOHW_GetStatus (
void
)
{
UNSIGNED32 *pCSR; // pointer into SFR space
// Set SFR pointer
pCSR = (UNSIGNED32 *) &C1SR + (FIRST_CANPORT-1)*0x1000;
if ((mTxIn != mTxOut) && (!(*pCSR & 0x00000004L)))
{ // Busy transmitting
mStatus |= HW_TXBSY;
}
else
{ // all Tx buffers empty
mStatus &= ~HW_TXBSY;
}
return mStatus;
}
/**************************************************************************
DOES: This function implements a CAN receive queue. With each
function call a message is pulled from the queue.
RETURNS: 1 Message was pulled from receive queue
0 Queue empty, no message received
**************************************************************************/
UNSIGNED8 MCOHW_PullMessage (CAN_MSG MEM_FAR *pReceiveBuf)
{
UNSIGNED16 obj;
UNSIGNED32 *pSrc; // Source Pointer
UNSIGNED32 *pDst; // Destination Pointer
obj = 0;
pDst = (UNSIGNED32 *) &(pReceiveBuf->BUF[0]);
pSrc = (UNSIGNED32 *) &(gFullCANList[0].Dat1);
while (obj < gCANFilter)
{
// if its currently updated, we come back next time and do not wait here
// semaphore set to 11?
if ((*pSrc & 0x03000000L) == 0x03000000L)
{ // Object Updated since last access
*pSrc &= 0xFCFFFFFF; // clear Semaphore
pSrc++; // Set to DatA
*pDst = *pSrc; // Copy DatA
pSrc++; // Set to DatB
pDst++; // Set to DatB
*pDst = *pSrc; // Copy DatB
pSrc -= 2; // Back to Dat1
pReceiveBuf->ID = (UNSIGNED16) *pSrc & 0x07FF;
pReceiveBuf->LEN = (UNSIGNED8) (*pSrc >> 16) & 0x0F;
// Re-read semaphore
if ((*pSrc & 0x03000000L) == 0)
{ // Only return it, if not updated while reading
return 1;
}
}
obj ++; // Next message object buffer
pSrc += 3; // Next record in gFullCANList array
}
return 0; // Return False, no msg rcvd
}
/**************************************************************************
DOES: If there is something in the transmit queue, and if the transmit
buffer is available, copy next message from queue to transmit buffer
***************************************************************************/
void MCOHW_CheckTxQueue (
void
)
{
UNSIGNED32 *pCSR; // pointer into SFR space
CAN_MSG *pMsg;
UNSIGNED32 *pAddr;
UNSIGNED32 *pCandata;
// Set SFR pointer
pCSR = (UNSIGNED32 *) &C1SR + (FIRST_CANPORT-1)*0x1000;
if ((*pCSR & 0x00000004L) && (mTxIn != mTxOut))
{ // Transmit Channel 1 is available and message is in queue
pMsg = &(mTxQueue[(mTxOut)&(TXQUEUESIZE-1)]);
pAddr = (UNSIGNED32 *) &C1TFI1 + (FIRST_CANPORT-1)*0x1000;
// Write DLC
*pAddr = ((UNSIGNED32) (pMsg->LEN)) << 16;
// Write RTR flag if needed
/*
if (pMsg->ID & CANID_RTR)
{
*pAddr |= (1 << 30);
}
*/
// Write CAN ID
pAddr++;
*pAddr = pMsg->ID & 0x000007FFL;
// Write first 4 data bytes
pCandata = (UNSIGNED32 *) &(pMsg->BUF[0]);
pAddr++;
*pAddr = *pCandata;
// Write second 4 data bytes
pCandata++;
pAddr++;
*pAddr = *pCandata;
// Write transmission request
pAddr = (UNSIGNED32 *) &C1CMR + (FIRST_CANPORT-1)*0x1000;
*pAddr = 0x21; // Transmission Request Buf 1
// Update Out pointer
mTxOut++;
mTxOut &= (TXQUEUESIZE-1);
}
}
/**************************************************************************
DOES: Adding a CAN message to the transmit queue
RETURNS: TRUE or FALSE if queue overrun
***************************************************************************/
UNSIGNED8 MCOHW_PushMessage (
CAN_MSG *pTransmitBuf // Data structure with message to be send
)
{
// Copy message to transmit queue
memcpy((UNSIGNED32 *) &(mTxQueue[mTxIn]),
(UNSIGNED32 *) pTransmitBuf,
sizeof(CAN_MSG));
// Increment IN pointer (0-7)
mTxIn++;
mTxIn &= (TXQUEUESIZE-1);
// Check for overrun
if (mTxIn == mTxOut)
{ // Overrun occured
// Increment OUT pointer (one message lost)
mTxOut++;
mTxOut &= (TXQUEUESIZE-1);
// Signal overrun to status variable
mStatus |= HW_TXOR;
return FALSE;
}
VICSoftInt = 0x00100000; // Trigger Tx complete interrupt
return TRUE;
}
/**************************************************************************
DOES: LPC2000 default interrupt handler
**************************************************************************/
void MCOHW_DefaultISR (
void
)
{
VICVectAddr = 0xFFFFFFFF; // Acknowledge Interrupt
}
/**************************************************************************
DOES: CAN error interrupt handler
**************************************************************************/
void MCOHW_CANISR_Err (
void
)
{
// INSERT APPLICATION SPECIFIC CODE
mStatus |= HW_CERR;
VICVectAddr = 0xFFFFFFFF; // Acknowledge Interrupt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -