drivers/can_peak/can_peak.c
author etisserant
Fri, 06 Apr 2007 16:49:28 +0200
changeset 149 fe50ada8020b
parent 35 88812de1d7cc
permissions -rw-r--r--
Changes in the API:
- No more mandatory callbacks declared for each node anymore
heartbeatError
SDOtimeoutError
initialisation
preOperational
operational
stopped
post_sync
post_TPDO
canSend

- Fill function ptr to declare callbacks
CO_Data.heartbeatError
CO_Data.SDOtimeoutError
CO_Data.initialisation
CO_Data.preOperational
CO_Data.operational
CO_Data.stopped
CO_Data.post_sync
CO_Data.post_TPDO

- CanClose now takes CO_Data* as parameter
- canSend is provided to the stack directly by OS interface, no specific callback.
/*
This file is part of CanFestival, a library implementing CanOpen Stack. 

Copyright (C): Edouard TISSERANT and Francis DUPIN

See COPYING file for copyrights details.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stddef.h> /* for NULL */
#include <sys/ioctl.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>

/* driver pcan pci for Peak board */
//#include "libpcan.h"
//#include "pcan.h"

#include "libpcan.h" // for CAN_HANDLE

#include <applicfg.h>
#include "timer.h"
#include "can_driver.h"
#include "timers_driver.h"

#define MAX_NB_CAN_PORTS 16

typedef struct {
  char used;
  HANDLE fd;
  TASK_HANDLE receiveTask;
  CO_Data* d;
} CANPort;

CANPort canports[MAX_NB_CAN_PORTS] = {{0,},};

// Define for rtr CAN message
#define CAN_INIT_TYPE_ST_RTR MSGTYPE_STANDARD | MSGTYPE_RTR 

/*********functions which permit to communicate with the board****************/
UNS8 canReceive(CAN_HANDLE fd0, Message *m)
{
  UNS8 data; 
  TPCANMsg peakMsg;
  if ((errno = CAN_Read(((CANPort*)fd0)->fd, & peakMsg))) {		// Blocks until no new message or error.
    if(errno != -EIDRM && errno != -EPERM) // error is not "Can Port closed while reading" 
    {
    	perror("!!! Peak board : error of reading. (from f_can_receive function) \n");
    }
    return 1;
  }
  m->cob_id.w = peakMsg.ID;   
  if (peakMsg.MSGTYPE == CAN_INIT_TYPE_ST)         	/* bits of MSGTYPE_*/
    m->rtr = 0;
  else 
    m->rtr = 1;
  m->len = peakMsg.LEN;					/* count of data bytes (0..8) */
  for(data = 0  ; data < peakMsg.LEN ; data++)             			
    m->data[data] = peakMsg.DATA[data];         	/* data bytes, up to 8 */
  
  return 0;
}

void canReceiveLoop(CAN_HANDLE fd0)
{
	CO_Data* d = ((CANPort*)fd0)->d;
	Message m;
	while (1) {
		if(!canReceive(fd0, &m))
		{
			EnterMutex();
			canDispatch(d, &m);
			LeaveMutex();
		}else{
//			printf("canReceive returned error\n");
			break;
		}
	}
}

/***************************************************************************/
UNS8 canSend(CAN_HANDLE fd0, Message *m)
{
  UNS8 data;
  TPCANMsg peakMsg;
  peakMsg.ID=m -> cob_id.w;              			/* 11/29 bit code */
  if(m->rtr == 0)	
    peakMsg.MSGTYPE = CAN_INIT_TYPE_ST;       /* bits of MSGTYPE_*/
  else {
    peakMsg.MSGTYPE = CAN_INIT_TYPE_ST_RTR;       /* bits of MSGTYPE_*/
  }
  peakMsg.LEN = m->len;   
          			/* count of data bytes (0..8) */
  for(data = 0 ; data <  m->len; data ++)
  	peakMsg.DATA[data] = m->data[data];         	/* data bytes, up to 8 */
  
  if((errno = CAN_Write(((CANPort*)fd0)->fd, & peakMsg))) {
    perror("!!! Peak board : error of writing. (from canSend function) \n");
    return 1;
  }
  return 0;

}

/***************************************************************************/
CAN_HANDLE canOpen(s_BOARD *board)
{
  HANDLE fd0 = NULL;
  char busname[64];
  char* pEnd;
  int i;  
  
  for(i=0; i < MAX_NB_CAN_PORTS; i++)
  {
  	if(!canports[i].used)
	  	break;
  }

  if(strtol(board->busname, &pEnd,0) >= 0)
  {
    sprintf(busname,"/dev/pcan%s",board->busname);
    fd0 = LINUX_CAN_Open(busname, O_RDWR);
  }

  if (i==MAX_NB_CAN_PORTS || fd0 == NULL)
    {
      fprintf (stderr, "Open failed.\n");
      return (CAN_HANDLE)NULL;
    }

   CAN_Init(fd0, board->baudrate, CAN_INIT_TYPE_ST);

   canports[i].used = 1;
   canports[i].fd = fd0;

   canports[i].d = board->d;
   CreateReceiveTask((CANPort*) &canports[i], &canports[i].receiveTask);

   return (CANPort*) &canports[i];
}

/***************************************************************************/
int canClose(CAN_HANDLE fd0)
{
  CAN_Close(((CANPort*)fd0)->fd);
  WaitReceiveTaskEnd(&((CANPort*)fd0)->receiveTask);
  ((CANPort*)fd0)->used = 0;
  return 0;
}