b769685b66
updated code files git-svn-id: file:///srv/dev-disk-by-uuid-17e88007-4d0c-45e0-8757-cacfcc458630/repositories/svn/Diplomarbeit@132 9fe90eed-be63-e94b-8204-d34ff4c2ff93
461 lines
17 KiB
C
461 lines
17 KiB
C
/* ---------------------------------------------------------------------------
|
|
* can.c (c) 2008 Micro-key bv
|
|
* ---------------------------------------------------------------------------
|
|
* Micro-key bv
|
|
* Industrieweg 28, 9804 TG Noordhorn
|
|
* Postbus 92, 9800 AB Zuidhorn
|
|
* The Netherlands
|
|
* Tel: +31 594 503020
|
|
* Fax: +31 594 505825
|
|
* Email: support@microkey.nl
|
|
* Web: www.microkey.nl
|
|
* ---------------------------------------------------------------------------
|
|
* Description:
|
|
* ---------------------------------------------------------------------------
|
|
* Version(s): 0.1, Dez 11, 2008, MMi
|
|
* Creation.
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
|
|
/* ---------------------------------------------------------------------------
|
|
* System include files
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
/* Hardware Includes */
|
|
#include "LPC23xx.h"
|
|
#include "types.h"
|
|
|
|
/* FreeRTOS includes */
|
|
#include "FreeRTOS.h"
|
|
#include "Task.h"
|
|
#include "queue.h"
|
|
/* ---------------------------------------------------------------------------
|
|
* Application include files
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
#include "can.h"
|
|
#include "SerOut.h"
|
|
#include "armVIC.h"
|
|
/* ---------------------------------------------------------------------------
|
|
* Local constant and macro definitions
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
#define CAN_PORT 2
|
|
/* ---------------------------------------------------------------------------
|
|
* Global variable definitions
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
static UINT32 debugVar = 0;
|
|
static UINT32 debugCnt = 0;
|
|
/* ---------------------------------------------------------------------------
|
|
* Local variable definitions
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
UINT16 volatile gCANFilter = 0; /* Number of global set filters */
|
|
|
|
CAN_MSG volatile gCANList[MAX_FILTERS]; /* CAN message list */
|
|
/* ---------------------------------------------------------------------------
|
|
* Local function definitions
|
|
* ---------------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
UINT16 CANInit (UINT32 can_btr)
|
|
{
|
|
|
|
PCONP |= (1 << 14); /* power on CAN2 */
|
|
|
|
|
|
/* Enable Pins for CAN interface */
|
|
/* Set P0.4 to function 10 (RD2) */
|
|
PINSEL0 &=~(1 << 8); /* Clear Bit 8 in PINSEL0 */
|
|
PINSEL0 |= (1 << 9); /* set bit 9 in PINSEL0 */
|
|
/* Set P0.5 to function 10 (TD2) */
|
|
PINSEL0 &=~(1 << 10); /* Clear bit 10 in PINSEL0 */
|
|
PINSEL0 |= (1 << 11); /* Set bit 11 in PINSEL0 */
|
|
|
|
gCANFilter = 0; /* Reset previous Filters */
|
|
// CAN_AFMR = 0x00000001L; /* Switch off Aceptance Filter */
|
|
|
|
CAN2MOD = 0x00000001; /* Set Mode to Reset (Bit 0) */
|
|
CAN2IER = 0x00000000; /* Disable all CAN2 Interrupts */
|
|
CAN2GSR = 0x00000000; /* Clear all status bits */
|
|
CAN2BTR = can_btr; /* Set bus timing */
|
|
|
|
/* Set Address of CAN ISR to Vectored Interrupt Address 23 */
|
|
VICVectAddr23 = (unsigned long) CAN_IRS_Handler;
|
|
VICVectCntl23 = 1; /* Set a low interrupt priority */
|
|
VICIntEnable |= (1 << 23); /* Enable CAN interrupt */
|
|
|
|
// CAN2IER = 0x00000081; /* Enable all RX and Err IRQs */
|
|
CAN2IER = 0x00000001; /* Enable all RX IRQs */
|
|
CAN2MOD = 0x00000000; /* Set Mode to Normal (Bit 0) */
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
UINT16 CANSetFilter (UINT32 CANID)
|
|
{
|
|
UINT32 loopcnt = 0;
|
|
UINT32 regbuffer = 0;
|
|
UINT32 buf0;
|
|
UINT32 buf1;
|
|
UINT32 ID_lower;
|
|
UINT32 ID_upper;
|
|
UINT32 *pAddr;
|
|
|
|
CAN_AFMR = 0x00000001L; /* Switch off Acceptance filter */
|
|
|
|
if (gCANFilter == 0)
|
|
{
|
|
/* First filter set - Init Entry of position Zero */
|
|
/* Make first array entry for CAN device 1
|
|
* This is necessary due to the following sort algorithm
|
|
*/
|
|
gCANList[0].Dat1 = 0x000037FFL;
|
|
}
|
|
|
|
if (gCANFilter >= MAX_FILTERS)
|
|
{
|
|
/* If Array index exceeds the limit, return with error */
|
|
return (FALSE);
|
|
}
|
|
|
|
CANID &= 0x000007FFL; /* Mask the 11-bit ID */
|
|
CANID |= ((CAN_PORT - 1) << 13); /* Add PORT# to ID */
|
|
|
|
/* Filters must be sorted by interface, then by priority */
|
|
|
|
/* Algorithm to sort new entry into excisting array */
|
|
while (loopcnt < gCANFilter) /* Look through all entries */
|
|
{
|
|
if ((gCANList[loopcnt].Dat1 & 0x0000FFFFL)> CANID)
|
|
{
|
|
/* Found position to insert new entry */
|
|
break;
|
|
}
|
|
loopcnt++;
|
|
}
|
|
|
|
buf0 = gCANList[loopcnt].Dat1; /* Buffer old array entry */
|
|
gCANList[loopcnt].Dat1 = CANID; /* Insert the new entry */
|
|
|
|
/* move all remaining entries one position up */
|
|
gCANFilter++; /* Increase Filter counter */
|
|
while (loopcnt < gCANFilter)
|
|
{
|
|
loopcnt++;
|
|
buf1 = gCANList[loopcnt].Dat1;
|
|
gCANList[loopcnt].Dat1 = buf0;
|
|
buf0 = buf1;
|
|
}
|
|
|
|
|
|
CAN_SFF_SA = regbuffer; /* Set Std Frame Start Address */
|
|
/* Set pointer to the Filter RAM base Address */
|
|
pAddr = ( UINT32 *) ACCEPTANCE_FILTER_RAM_BASE;
|
|
|
|
for (loopcnt = 0; loopcnt < ((gCANFilter + 1) / 2); loopcnt++)
|
|
{
|
|
ID_lower = gCANList[loopcnt * 2].Dat1 & 0x0000FFFFL;
|
|
ID_upper = gCANList[loopcnt * 2 + 1].Dat1 & 0x0000FFFFL;
|
|
// candata = (ID_lower << 16) + ID_upper; // \TODO IS THIS WORKING?
|
|
// *pAddr = candata;
|
|
*pAddr = (ID_lower << 16) + ID_upper;
|
|
regbuffer += 4;
|
|
pAddr++;
|
|
}
|
|
|
|
/* regbuffer points to the End of the Table */
|
|
|
|
CAN_SFF_GRP_SA = regbuffer; /* Set Std Group Start Address */
|
|
|
|
// Set pointer for Extended Frame Individual
|
|
// Extended Frame Start Address Register
|
|
CAN_EFF_SA = regbuffer; /* Set Extd. Frame Start Address*/
|
|
|
|
CAN_EFF_GRP_SA = regbuffer; /* Set Extd. Group Start Address*/
|
|
|
|
CAN_EOT = regbuffer; /* Set End of Table */
|
|
|
|
CAN_AFMR = 0; /* enable Acception Filter */
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
UINT16 CANPushMessage (CAN_MSG *pTransmitBuf)
|
|
{
|
|
UINT32 *pAddr;
|
|
UINT32 *pCandata;
|
|
UINT8 TXBufOffset;
|
|
|
|
pAddr = (UINT32 *) &CAN2SR; // CANSR
|
|
|
|
/* Check if one of the three transmit buffers are available, use first */
|
|
if (!(*pAddr & 0x00000004L))
|
|
{
|
|
/* First Buffer is not available */
|
|
if (!(*pAddr & 0x00000400L))
|
|
{
|
|
/* Second Buffer is not available */
|
|
if (!(*pAddr & 0x00040000L))
|
|
{
|
|
/* Third Buffer is not available -> No Buffer available */
|
|
return (FALSE); /* Abort transmission, Error */
|
|
}
|
|
else
|
|
{
|
|
/* Third Buffer is available, set Buffer offset */
|
|
TXBufOffset = 0x08;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Second Buffer is available, set Buffer offset */
|
|
TXBufOffset = 0x04;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* First Buffer is available, set Buffer offset */
|
|
TXBufOffset = 0x00;
|
|
}
|
|
|
|
/* Write Data to Transmit Frame Information Register */
|
|
pAddr = (UINT32 *) &CAN2TFI1 + TXBufOffset; /* Set pointer to CAN2TFIx */ // \TODO WATCH HERE (had offset)!!!
|
|
*pAddr = (pTransmitBuf->Dat1 & 0x000F0000L);
|
|
|
|
/* Write CAN ID to Transmit Identifier Register */
|
|
pAddr++; /* Increase pointer to CAN2TIDx */
|
|
*pAddr = pTransmitBuf->Dat1 & 0x000007FFL;
|
|
|
|
/* Write first four Bytes to Transmit Data Register A */
|
|
pCandata = (UINT32 *) &(pTransmitBuf->DatA); /* Get first 4 bytes */
|
|
pAddr++; /* Set pointer to DataA register*/
|
|
*pAddr = *pCandata; /* Write first 4 bytes to DataA */
|
|
|
|
/* Write second four Bytes to Transmit Data Register B */
|
|
pCandata++; /* Get second four bytes */
|
|
pAddr++; /* Point to DataB register */
|
|
*pAddr = *pCandata; /* Write second 4 Bytes to DataB*/
|
|
|
|
|
|
/* Write Transmission Request to CAN2 Command Register
|
|
* This Action is depending on the chosen transmission buffer (1-3)
|
|
* Two bits must be written - Bit (0): (TR) Transmission Request
|
|
* Bit (5|6|7): (STBx) Select Buffer (1|2|3)
|
|
*/
|
|
if (TXBufOffset == 0x00)
|
|
{
|
|
/* First buffer was chosen. Write TR and STB1 */
|
|
CAN2CMR = 0x21;
|
|
}
|
|
else if (TXBufOffset == 0x04)
|
|
{
|
|
/* Second buffer was chosen. Write TR and STB2 */
|
|
CAN2CMR = 0x41;
|
|
}
|
|
else if (TXBufOffset == 0x08)
|
|
{
|
|
/* Third buffer was chosen. Write TR and STB3 */
|
|
CAN2CMR = 0x81;
|
|
}
|
|
else
|
|
{
|
|
/* No Buffer was chosen, return with error (should not come here) */
|
|
return (FALSE);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
UINT16 CANPullMessage (CAN_MSG *pReceiveBuf)
|
|
{
|
|
UINT32 loopcnt = 0;
|
|
UINT32 *pSrc;
|
|
UINT32 *pDst;
|
|
UINT32 match;
|
|
|
|
|
|
/* Initialise Source and Destination Pointer */
|
|
pSrc = (UINT32 *) &(gCANList[0].Dat1);
|
|
pDst = (UINT32 *) &(pReceiveBuf->Dat1);
|
|
|
|
/* Prepare match value for CAN interface */
|
|
match = CAN_PORT << 13;
|
|
match |= 0x03000000L; /* Semaphore bits are 11b */
|
|
|
|
while (loopcnt < gCANFilter)
|
|
{
|
|
/* Scan for every set Filter */
|
|
if ((*pSrc & 0x0300E000L) == match)
|
|
{
|
|
/* A new Message is detected in Source Array */
|
|
*pSrc &= 0xFCFFFFFFL; /* clear Semaphore */
|
|
|
|
*pDst = *pSrc; /* Copy Dat1 from SRC to DST */
|
|
|
|
pSrc++; /* Set SRC-Pointer to SRC.DataA */
|
|
pDst++; /* Set DST-Pointer to DST.DataA */
|
|
|
|
*pDst = *pSrc; /* Copy DatA from SRC to DST */
|
|
|
|
pSrc++; /* Set SRC-Pointer to SRC.DataB */
|
|
pDst++; /* Set DST-Pointer to DST.DataB */
|
|
|
|
*pDst = *pSrc; /* Copy DatB from SRC to DST */
|
|
|
|
pSrc -= 2; // Reset SRC-Pointer to Dat1 */
|
|
pDst -= 2; // Reset DST-Pointer to Dat1 */
|
|
|
|
if ((*pSrc & 0x03000000L) == 0)
|
|
{
|
|
/* If actual SRC was updated while reading, return to caller
|
|
* This is to prevent of ignoring the message that came in while
|
|
* reading, which would not be noticed if the message counter
|
|
* will be increased like the loop will do in the next step
|
|
*/
|
|
return (TRUE);
|
|
}
|
|
}
|
|
loopcnt++; /* Go to next Message in Buffer */
|
|
pSrc += 3; /* Increase SRC-Pointer to next */
|
|
}
|
|
return (FALSE); /* Return False if no Message in*/
|
|
}
|
|
|
|
|
|
void CAN_IRS_Handler()
|
|
{
|
|
UINT32 CANStatus;
|
|
|
|
ISR_ENTRY();
|
|
CANStatus = CAN_RX_SR;
|
|
if (CANStatus & (1 << 8))
|
|
{
|
|
/* A received Message is available in CAN1 controller */
|
|
CAN_CANISR_Rx1();
|
|
}
|
|
if (CANStatus & (1 << 9))
|
|
{
|
|
/* A received Message is available in CAN2 controller */
|
|
CAN_CANISR_Rx2();
|
|
}
|
|
|
|
/* Error Interrupts are currently disabled due to purpose of CAN driver */
|
|
if (CAN_MSR & (1 << 1))
|
|
{
|
|
/* At least one Error-Counter of CAN2 has reached the limit */
|
|
CAN_CANISR_Err();
|
|
}
|
|
if (CAN1GSR & (1 << 6 ))
|
|
{
|
|
/* The error count includes both TX and RX */
|
|
}
|
|
if (CAN2GSR & (1 << 6 ))
|
|
{
|
|
/* The error count includes both TX and RX */
|
|
}
|
|
if (CAN2ICR & (1 << 7))
|
|
{
|
|
/* Error-on-Bus Interrupt detected */
|
|
CAN_ERRORBUS();
|
|
}
|
|
|
|
VICVectAddr = 0; /* Acknowledge Interrupt */
|
|
|
|
ISR_EXIT();
|
|
}
|
|
|
|
|
|
void CAN_CANISR_Rx1 (void)
|
|
{
|
|
UINT32 buf;
|
|
UINT32 *pDest;
|
|
|
|
if (!(CAN1RFS & 0xC0000400L))
|
|
{ // 11-bit ID, no RTR, matched a filter
|
|
|
|
// initialize destination pointer
|
|
// filter number is in lower 10 bits of C1RFS
|
|
pDest = (UINT32 *) &(gCANList[(CAN1RFS & 0x000003FFL)].Dat1);
|
|
|
|
// calculate contents for first entry into CAN list
|
|
buf = CAN1RFS & 0xC00F0000L; // mask FF, RTR and DLC
|
|
buf |= 0x01002000L; // set semaphore to 01b and CAN port to 1
|
|
buf |= CAN1RID & 0x000007FFL; // get CAN message ID
|
|
|
|
// now copy entire message to CAN list
|
|
*pDest = buf;
|
|
pDest++; // set to gCANList[(C1RFS & 0x000003FFL)].DatA
|
|
*pDest = CAN1RDA;
|
|
pDest++; // set to gCANList[(C1RFS & 0x000003FFL)].DatB
|
|
*pDest = CAN1RDB;
|
|
|
|
// now set the sempahore to complete
|
|
buf |= 0x03000000L; // set semaphore to 11b
|
|
pDest -= 2; // set to gCANList[(C1RFS & 0x000003FFL)].Dat1
|
|
*pDest = buf;
|
|
}
|
|
|
|
CAN1CMR = 0x04; // release receive buffer
|
|
}
|
|
|
|
|
|
void CAN_CANISR_Rx2(void)
|
|
{
|
|
UINT32 buf;
|
|
UINT32 *pDest;
|
|
|
|
debugVar = 0x00000001;
|
|
|
|
if (!(CAN2RFS & 0xC0000400L))
|
|
{
|
|
/* 11-bit ID, no RTR */
|
|
debugVar = 0x00000011;
|
|
/* initialize Destination Pointer */
|
|
/* Filter Nmber is in bit 0-9 of CAN2RFS */
|
|
pDest = (UINT32 *) &(gCANList[(CAN2RFS & 0x000003FFL)].Dat1);
|
|
// pDest = (UINT32 *) &(gCANList[(1)].Dat1);
|
|
|
|
/* Calculate contents for first entry into CAN list */
|
|
buf = CAN2RFS & 0xC00F0000L; /* Mask FF, RTR and DLC */
|
|
buf |= 0x01004000L; /* set sema to 01b and port to 2*/
|
|
buf |= CAN2RID & 0x000007FFL; /* get CAN message ID */
|
|
|
|
/* Copy entire message to CAN list */
|
|
*pDest = buf; /* Copy Dat1 to DST */
|
|
pDest++; /* Set Pointer to DataA */
|
|
*pDest = CAN2RDA; /* copy DataA */
|
|
pDest++; /* Set Pointer to DataB */
|
|
*pDest = CAN2RDB; /* Copy DataB */
|
|
|
|
|
|
buf |= 0x03000000L; /* semaphore to 11b (complete) */
|
|
pDest -= 2; /* Set back to Dat1 */
|
|
*pDest = buf; /* update semaphore in DST */
|
|
}
|
|
|
|
debugCnt++;
|
|
CAN2CMR = 0x04; /* Release Receive Buffer */
|
|
}
|
|
|
|
|
|
void CAN_CANISR_Err (void)
|
|
{
|
|
|
|
}
|
|
|
|
void CAN_ERRORBUS (void)
|
|
{
|
|
volatile UINT32 regRead;
|
|
|
|
regRead = CAN2ICR;
|
|
|
|
debugPrint("released");
|
|
}
|