drivers/AT91/can_AT91.c
author Edouard Tisserant
Sat, 21 Jan 2012 19:32:58 +0100
changeset 690 1c2cb6088050
parent 520 cc993e72b7e6
permissions -rw-r--r--
Merge further Ica changes
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
}