drivers/AT91/can_AT91.c
author Robert Lehmann <robert.lehmann@sitec-systems.de>
Tue, 28 Jul 2015 16:36:55 +0200
changeset 793 72e9e1064432
parent 520 cc993e72b7e6
permissions -rw-r--r--
timers_unix: Fix termination problem of WaitReceiveTaskEnd

The function pthread_kill sends the Signal thread and to the own process.
If you use this construct than the application which calls uses the
canfestival api will terminate at the call of canClose. To avoid that
use pthread_cancel instead of pthread_kill. To use the pthread_cancel call
you need to set the cancel ability in the thread function. That means
you need to call pthread_setcancelstate and pthread_setcanceltype.
For the termination of the thread at any time it is important to set the
cancel type to PTHREAD_CANCEL_ASYNCHRONOUS.
520
peter
parents:
diff changeset
     1
/*
peter
parents:
diff changeset
     2
This file is part of CanFestival, a library implementing CanOpen Stack.
peter
parents:
diff changeset
     3
peter
parents:
diff changeset
     4
Copyright (C): Edouard TISSERANT and Francis DUPIN
peter
parents:
diff changeset
     5
AT91 Port: Peter CHRISTEN
peter
parents:
diff changeset
     6
peter
parents:
diff changeset
     7
See COPYING file for copyrights details.
peter
parents:
diff changeset
     8
peter
parents:
diff changeset
     9
This library is free software; you can redistribute it and/or
peter
parents:
diff changeset
    10
modify it under the terms of the GNU Lesser General Public
peter
parents:
diff changeset
    11
License as published by the Free Software Foundation; either
peter
parents:
diff changeset
    12
version 2.1 of the License, or (at your option) any later version.
peter
parents:
diff changeset
    13
peter
parents:
diff changeset
    14
This library is distributed in the hope that it will be useful,
peter
parents:
diff changeset
    15
but WITHOUT ANY WARRANTY; without even the implied warranty of
peter
parents:
diff changeset
    16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
peter
parents:
diff changeset
    17
Lesser General Public License for more details.
peter
parents:
diff changeset
    18
peter
parents:
diff changeset
    19
You should have received a copy of the GNU Lesser General Public
peter
parents:
diff changeset
    20
License along with this library; if not, write to the Free Software
peter
parents:
diff changeset
    21
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
peter
parents:
diff changeset
    22
*/
peter
parents:
diff changeset
    23
peter
parents:
diff changeset
    24
//#define DEBUG_WAR_CONSOLE_ON
peter
parents:
diff changeset
    25
//#define DEBUG_ERR_CONSOLE_ON
peter
parents:
diff changeset
    26
peter
parents:
diff changeset
    27
#include "can_AT91.h"
peter
parents:
diff changeset
    28
#include "canfestival.h"
peter
parents:
diff changeset
    29
peter
parents:
diff changeset
    30
void can_irq_handler(void);
peter
parents:
diff changeset
    31
peter
parents:
diff changeset
    32
unsigned char canInit(unsigned int bitrate)
peter
parents:
diff changeset
    33
/******************************************************************************
peter
parents:
diff changeset
    34
Initialize the hardware to receive CAN messages and start the timer for the
peter
parents:
diff changeset
    35
CANopen stack.
peter
parents:
diff changeset
    36
INPUT	
peter
parents:
diff changeset
    37
OUTPUT	
peter
parents:
diff changeset
    38
******************************************************************************/
peter
parents:
diff changeset
    39
{
peter
parents:
diff changeset
    40
  unsigned char i;
peter
parents:
diff changeset
    41
  AT91S_CAN_MB *mb_ptr = AT91C_BASE_CAN_MB0;
peter
parents:
diff changeset
    42
peter
parents:
diff changeset
    43
  // Enable CAN PIOs
peter
parents:
diff changeset
    44
  AT91F_CAN_CfgPIO();
peter
parents:
diff changeset
    45
  // Enable CAN Clock
peter
parents:
diff changeset
    46
  AT91F_CAN_CfgPMC();
peter
parents:
diff changeset
    47
peter
parents:
diff changeset
    48
  // Enable CAN Transceiver
peter
parents:
diff changeset
    49
  AT91F_PIOA_CfgPMC();
peter
parents:
diff changeset
    50
peter
parents:
diff changeset
    51
  // Init CAN Interrupt Source Level
peter
parents:
diff changeset
    52
  AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,				// CAN base address
peter
parents:
diff changeset
    53
                        AT91C_ID_CAN,				// CAN ID
peter
parents:
diff changeset
    54
                        AT91C_AIC_PRIOR_HIGHEST,		// Max priority
peter
parents:
diff changeset
    55
                        AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,	// Level sensitive
peter
parents:
diff changeset
    56
                        can_irq_handler);			// C Handler
peter
parents:
diff changeset
    57
peter
parents:
diff changeset
    58
  AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_CAN);
peter
parents:
diff changeset
    59
peter
parents:
diff changeset
    60
  if (bitrate <= 500)
peter
parents:
diff changeset
    61
  {
peter
parents:
diff changeset
    62
    // CANopen 10..500 kbit with 16 tq, sample point is at 14 tq
peter
parents:
diff changeset
    63
    // all values are added to 1 by hardware
peter
parents:
diff changeset
    64
    // Resynchronisation jump width (SJW)	= 1 tq
peter
parents:
diff changeset
    65
    // Propagation Time Segment (PRS)		= 5 tq
peter
parents:
diff changeset
    66
    // Phase Segment 1 (PHS1)			= 8 tq
peter
parents:
diff changeset
    67
    // Phase Segment 2 (PHS2)			= 2 tq
peter
parents:
diff changeset
    68
    // Total					= 16 tq
peter
parents:
diff changeset
    69
    AT91F_CAN_CfgBaudrateReg(AT91C_BASE_CAN,
peter
parents:
diff changeset
    70
                             (AT91C_MASTER_CLOCK/16/1000/bitrate - 1) << 16 | 0x0471);
peter
parents:
diff changeset
    71
  }
peter
parents:
diff changeset
    72
  else
peter
parents:
diff changeset
    73
    return 0;
peter
parents:
diff changeset
    74
peter
parents:
diff changeset
    75
  // Enable CAN and Wait for WakeUp Interrupt
peter
parents:
diff changeset
    76
//  AT91F_CAN_EnableIt(AT91C_BASE_CAN, AT91C_CAN_WAKEUP);
peter
parents:
diff changeset
    77
  AT91F_CAN_CfgModeReg(AT91C_BASE_CAN, AT91C_CAN_CANEN);
peter
parents:
diff changeset
    78
peter
parents:
diff changeset
    79
  // Reset all mailsboxes (MBs), filters are zero (accept all) by clear all MB
peter
parents:
diff changeset
    80
  // Set the lower MBs as rx buffer
peter
parents:
diff changeset
    81
  for (i = 0; i < NB_RX_MB; i++, mb_ptr++)
peter
parents:
diff changeset
    82
  // Configure receive MBs as receive buffer, last as receive overwrite
peter
parents:
diff changeset
    83
    AT91F_InitMailboxRegisters(mb_ptr,
peter
parents:
diff changeset
    84
				((i < (NB_RX_MB - 1)) ? AT91C_CAN_MOT_RX : AT91C_CAN_MOT_RXOVERWRITE)
peter
parents:
diff changeset
    85
				| AT91C_CAN_PRIOR,	// Mailbox Mode Reg
peter
parents:
diff changeset
    86
				0x00000000,		// Mailbox Acceptance Mask Reg
peter
parents:
diff changeset
    87
				0x00000000,		// Mailbox ID Reg
peter
parents:
diff changeset
    88
				0x00000000,		// Mailbox Data Low Reg
peter
parents:
diff changeset
    89
				0x00000000,		// Mailbox Data High Reg
peter
parents:
diff changeset
    90
				0x00000000);		// Mailbox Control Reg
peter
parents:
diff changeset
    91
  for (   ; i < NB_MB; i++, mb_ptr++)
peter
parents:
diff changeset
    92
  // Configure transmit MBs
peter
parents:
diff changeset
    93
    AT91F_InitMailboxRegisters(mb_ptr,
peter
parents:
diff changeset
    94
				AT91C_CAN_MOT_TX
peter
parents:
diff changeset
    95
				| AT91C_CAN_PRIOR,	// Mailbox Mode Reg
peter
parents:
diff changeset
    96
				0x00000000,		// Mailbox Acceptance Mask Reg
peter
parents:
diff changeset
    97
				0x00000000,		// Mailbox ID Reg
peter
parents:
diff changeset
    98
				0x00000000,		// Mailbox Data Low Reg
peter
parents:
diff changeset
    99
				0x00000000,		// Mailbox Data High Reg
peter
parents:
diff changeset
   100
				0x00000000);		// Mailbox Control Reg
peter
parents:
diff changeset
   101
  // Enable Reception on all receive Mailboxes
peter
parents:
diff changeset
   102
  AT91F_CAN_InitTransferRequest(AT91C_BASE_CAN, RX_INT_MSK);
peter
parents:
diff changeset
   103
  // Enable all receive interrupts
peter
parents:
diff changeset
   104
  AT91F_CAN_EnableIt(AT91C_BASE_CAN, RX_INT_MSK);
peter
parents:
diff changeset
   105
  return 1;
peter
parents:
diff changeset
   106
}
peter
parents:
diff changeset
   107
peter
parents:
diff changeset
   108
unsigned char canSend(CAN_PORT notused, Message *m)
peter
parents:
diff changeset
   109
/******************************************************************************
peter
parents:
diff changeset
   110
The driver send a CAN message passed from the CANopen stack
peter
parents:
diff changeset
   111
INPUT	CAN_PORT is not used (only 1 avaiable)
peter
parents:
diff changeset
   112
	Message *m pointer to message to send
peter
parents:
diff changeset
   113
OUTPUT	1 if  hardware -> CAN frame
peter
parents:
diff changeset
   114
******************************************************************************/
peter
parents:
diff changeset
   115
{
peter
parents:
diff changeset
   116
  unsigned int mask;
peter
parents:
diff changeset
   117
  AT91S_CAN_MB *mb_ptr = AT91C_BASE_CAN_MB0 + START_TX_MB;
peter
parents:
diff changeset
   118
peter
parents:
diff changeset
   119
  if ((AT91F_CAN_GetStatus(AT91C_BASE_CAN) & TX_INT_MSK) == 0)
peter
parents:
diff changeset
   120
    return 0;			// No free MB for sending
peter
parents:
diff changeset
   121
peter
parents:
diff changeset
   122
  for (mask = 1 << START_TX_MB;
peter
parents:
diff changeset
   123
       (mask & TX_INT_MSK) && !(AT91F_CAN_GetStatus(AT91C_BASE_CAN) & mask);
peter
parents:
diff changeset
   124
	mask <<= 1, mb_ptr++)	// Search the first free MB
peter
parents:
diff changeset
   125
  {
peter
parents:
diff changeset
   126
  }
peter
parents:
diff changeset
   127
  AT91F_CAN_CfgMessageIDReg(mb_ptr, m->cob_id, 0);	// Set cob id
peter
parents:
diff changeset
   128
  // Mailbox Control Register, set remote transmission request and data lenght code
peter
parents:
diff changeset
   129
  AT91F_CAN_CfgMessageCtrlReg(mb_ptr, m->rtr ? AT91C_CAN_MRTR : 0 | (m->len << 16));	
peter
parents:
diff changeset
   130
  AT91F_CAN_CfgMessageDataLow(mb_ptr, *(UNS32*)(&m->data[0]));// Mailbox Data Low Reg
peter
parents:
diff changeset
   131
  AT91F_CAN_CfgMessageDataHigh(mb_ptr, *(UNS32*)(&m->data[4]));// Mailbox Data High Reg
peter
parents:
diff changeset
   132
  // Start sending by writing the MB configuration register to transmit
peter
parents:
diff changeset
   133
  AT91F_CAN_InitTransferRequest(AT91C_BASE_CAN, mask);
peter
parents:
diff changeset
   134
  return 1;	// successful
peter
parents:
diff changeset
   135
}
peter
parents:
diff changeset
   136
peter
parents:
diff changeset
   137
unsigned char canReceive(Message *m)
peter
parents:
diff changeset
   138
/******************************************************************************
peter
parents:
diff changeset
   139
The driver passes a received CAN message to the stack
peter
parents:
diff changeset
   140
INPUT	Message *m pointer to received CAN message
peter
parents:
diff changeset
   141
OUTPUT	1 if a message received
peter
parents:
diff changeset
   142
******************************************************************************/
peter
parents:
diff changeset
   143
{
peter
parents:
diff changeset
   144
  unsigned int mask;
peter
parents:
diff changeset
   145
  AT91S_CAN_MB *mb_ptr = AT91C_BASE_CAN_MB0;
peter
parents:
diff changeset
   146
peter
parents:
diff changeset
   147
  if ((AT91F_CAN_GetStatus(AT91C_BASE_CAN) & RX_INT_MSK) == 0)
peter
parents:
diff changeset
   148
    return 0;		// Nothing received
peter
parents:
diff changeset
   149
peter
parents:
diff changeset
   150
  for (mask = 1;
peter
parents:
diff changeset
   151
       (mask & RX_INT_MSK) && !(AT91F_CAN_GetStatus(AT91C_BASE_CAN) & mask);
peter
parents:
diff changeset
   152
	mask <<= 1, mb_ptr++)	// Search the first MB received
peter
parents:
diff changeset
   153
  {
peter
parents:
diff changeset
   154
  }
peter
parents:
diff changeset
   155
  m->cob_id = AT91F_CAN_GetFamilyID(mb_ptr);
peter
parents:
diff changeset
   156
  m->len = (AT91F_CAN_GetMessageStatus(mb_ptr) & AT91C_CAN_MDLC) >> 16;
peter
parents:
diff changeset
   157
  m->rtr = (AT91F_CAN_GetMessageStatus(mb_ptr) & AT91C_CAN_MRTR) ? 1 : 0;
peter
parents:
diff changeset
   158
  *(UNS32*)(&m->data[0]) = AT91F_CAN_GetMessageDataLow(mb_ptr);
peter
parents:
diff changeset
   159
  *(UNS32*)(&m->data[4]) = AT91F_CAN_GetMessageDataHigh(mb_ptr);
peter
parents:
diff changeset
   160
  // Enable Reception on Mailbox
peter
parents:
diff changeset
   161
  AT91F_CAN_CfgMessageModeReg(mb_ptr, AT91C_CAN_MOT_RX | AT91C_CAN_PRIOR);
peter
parents:
diff changeset
   162
  AT91F_CAN_InitTransferRequest(AT91C_BASE_CAN, mask);
peter
parents:
diff changeset
   163
  return 1;		// message received
peter
parents:
diff changeset
   164
}
peter
parents:
diff changeset
   165
peter
parents:
diff changeset
   166
/******************************************************************************
peter
parents:
diff changeset
   167
peter
parents:
diff changeset
   168
 ******************************* CAN INTERRUPT  *******************************/
peter
parents:
diff changeset
   169
peter
parents:
diff changeset
   170
void can_irq_handler(void)
peter
parents:
diff changeset
   171
/******************************************************************************
peter
parents:
diff changeset
   172
CAN Interrupt
peter
parents:
diff changeset
   173
******************************************************************************/
peter
parents:
diff changeset
   174
{
peter
parents:
diff changeset
   175
  volatile unsigned int status;
peter
parents:
diff changeset
   176
  static Message m = Message_Initializer;		// contain a CAN message
peter
parents:
diff changeset
   177
		
peter
parents:
diff changeset
   178
  status = AT91F_CAN_GetStatus(AT91C_BASE_CAN) & AT91F_CAN_GetInterruptMaskStatus(AT91C_BASE_CAN);
peter
parents:
diff changeset
   179
peter
parents:
diff changeset
   180
  if(status & RX_INT_MSK)
peter
parents:
diff changeset
   181
  {	// Rx Interrupt
peter
parents:
diff changeset
   182
    if (canReceive(&m))			// a message received
peter
parents:
diff changeset
   183
      canDispatch(&ObjDict_Data, &m);         // process it
peter
parents:
diff changeset
   184
  }
peter
parents:
diff changeset
   185
}