www.pudn.com > CAN_Ex1.rar > RTX_CAN.c


/*---------------------------------------------------------------------------- 
 *      R T L  -  C A N   D r i v e r 
 *---------------------------------------------------------------------------- 
 *      Name:    RTX_CAN.c 
 *      Purpose: CAN Generic Layer Driver 
 *      Rev.:    V3.12 
 *---------------------------------------------------------------------------- 
 *      This code is part of the RealView Run-Time Library. 
 *      Copyright (c) 2004-2007 KEIL - An ARM Company. All rights reserved. 
 *---------------------------------------------------------------------------*/ 
 
#include                       /* RTX kernel functions & defines      */ 
#include "CAN_Cfg.h"                  /* CAN Configuration                   */ 
#include "RTX_CAN.h"                  /* CAN Generic functions & defines     */ 
#include "CAN_Hw.h"                   /* CAN hw specific functions & defines */ 
 
#pragma diag_suppress 550 
 
/* Declare memory pool for CAN messages, both transmit and receive           */ 
CAN_msgpool_declare(CAN_mpool,CAN_CTRL_MAX_NUM*(CAN_No_SendObjects+CAN_No_ReceiveObjects)); 
 
/* Declare mailbox, for CAN transmit messages                                */ 
mbx_arr_declare(MBX_tx_ctrl,CAN_CTRL_MAX_NUM,CAN_No_SendObjects); 
 
/* Declare mailbox, for CAN receive messages                                 */ 
mbx_arr_declare(MBX_rx_ctrl,CAN_CTRL_MAX_NUM,CAN_No_ReceiveObjects); 
 
/* Semaphores used for protecting writing to CAN hardware                    */ 
OS_SEM wr_sem[CAN_CTRL_MAX_NUM]; 
 
 
/*---------------------------------------------------------------------------- 
 *      CAN RTX Generic Driver Functions 
 *---------------------------------------------------------------------------- 
 *  Functions implemented in this module: 
 *           CAN_ERROR CAN_mem_init  (void); 
 *           CAN_ERROR CAN_setup     (void) 
 *           CAN_ERROR CAN_init      (U32 ctrl, U32 baudrate) 
 *           CAN_ERROR CAN_start     (U32 ctrl) 
 *    static CAN_ERROR CAN_push      (U32 ctrl, CAN_msg *msg, U16 timeout) 
 *           CAN_ERROR CAN_send      (U32 ctrl, CAN_msg *msg, U16 timeout) 
 *           CAN_ERROR CAN_request   (U32 ctrl, CAN_msg *msg, U16 timeout) 
 *           CAN_ERROR CAN_set       (U32 ctrl, CAN_msg *msg, U16 timeout) 
 *    static CAN_ERROR CAN_pull      (U32 ctrl, CAN_msg *msg, U16 timeout) 
 *           CAN_ERROR CAN_receive   (U32 ctrl, CAN_msg *msg, U16 timeout) 
 *           CAN_ERROR CAN_rx_object (U32 ctrl, U32 ch, U32 id, CAN_FORMAT format) 
 *           CAN_ERROR CAN_tx_object (U32 ctrl, U32 ch, CAN_FORMAT format) 
 *---------------------------------------------------------------------------*/ 
 
 
/*--------------------------- CAN_init -------------------------------------- 
 * 
 *  The first time this function is called initialize the memory pool for  
 *  CAN messages and setup CAN controllers hardware 
 * 
 *  Initialize mailboxes for CAN messages and initialize CAN controller 
 * 
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x) 
 *              baudrate:   Baudrate 
 * 
 *  Return:     CAN_ERROR:  Error code 
 *---------------------------------------------------------------------------*/ 
 
CAN_ERROR CAN_init (U32 ctrl, U32 baudrate)  { 
  static U8 first_run_flag = 0; 
  CAN_ERROR error_code; 
  U32 ctrl0 = ctrl-1;                 /* Controller index 0 .. x-1           */ 
 
  /* Initialize the Semaphore before the first use */ 
  os_sem_init (wr_sem[ctrl0], 1); 
 
  /* When function is called for the first time it will initialize and setup  
     all of the resources that are common to CAN functionality               */ 
  if (first_run_flag == 0)  { 
    first_run_flag = 1; 
    if (_init_box (CAN_mpool, sizeof(CAN_mpool), sizeof(CAN_msg)) == 1) 
      return CAN_MEM_POOL_INIT_ERROR; 
  } 
 
  os_mbx_init (MBX_tx_ctrl[ctrl0], sizeof(MBX_tx_ctrl[ctrl0])); 
  os_mbx_init (MBX_rx_ctrl[ctrl0], sizeof(MBX_rx_ctrl[ctrl0])); 
 
  error_code = CAN_hw_setup (ctrl); 
  if (error_code != CAN_OK)  
    return error_code; 
 
  return (CAN_hw_init (ctrl, baudrate)); 
} 
 
 
/*--------------------------- CAN_start ------------------------------------- 
 * 
 *  Start CAN controller (enable it to participate on CAN network) 
 * 
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x) 
 * 
 *  Return:     CAN_ERROR:  Error code 
 *---------------------------------------------------------------------------*/ 
 
CAN_ERROR CAN_start (U32 ctrl)  { 
  return (CAN_hw_start (ctrl)); 
} 
 
 
/*--------------------------- CAN_push -------------------------------------- 
 * 
 *  Send CAN_msg if hardware is free for sending, otherwise push message to  
 *  message queue to be sent when hardware becomes free 
 * 
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x) 
 *              msg:        Pointer to CAN message to be sent 
 *              timeout:    Timeout value for message sending 
 * 
 *  Return:     CAN_ERROR:  Error code 
 *---------------------------------------------------------------------------*/ 
 
static CAN_ERROR CAN_push (U32 ctrl, CAN_msg *msg, U16 timeout)  { 
  CAN_msg *ptrmsg; 
  U32 ctrl0 = ctrl-1;                 /* Controller index 0 .. x-1           */ 
                                       
  if (CAN_hw_tx_empty (ctrl) == CAN_OK) { /* Transmit hardware free for send */ 
    CAN_hw_wr (ctrl, msg);            /* Send message                        */ 
  } 
  else {                              /* If hardware for sending is busy     */ 
    /* Write the message to send mailbox if there is room for it             */ 
    ptrmsg = _alloc_box (CAN_mpool); 
    if (ptrmsg != NULL) { 
      *ptrmsg = *msg; 
      /* If message hasn't been sent but timeout expired, deallocate memory  */ 
      if (os_mbx_send (MBX_tx_ctrl[ctrl0], ptrmsg, timeout) == OS_R_TMO) { 
        if (_free_box (CAN_mpool, ptrmsg) == 1) 
          return CAN_DEALLOC_MEM_ERROR; 
 
        return CAN_TIMEOUT_ERROR; 
      } 
    } else 
      return CAN_ALLOC_MEM_ERROR; 
  } 
  return CAN_OK; 
} 
 
 
/*--------------------------- CAN_send -------------------------------------- 
 * 
 *  Send DATA FRAME message, see CAN_push function comment 
 * 
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x) 
 *              msg:        Pointer to CAN message to be sent 
 *              timeout:    Timeout value for message sending 
 * 
 *  Return:     CAN_ERROR:  Error code 
 *---------------------------------------------------------------------------*/ 
 
CAN_ERROR CAN_send (U32 ctrl, CAN_msg *msg, U16 timeout)  { 
  msg->type = DATA_FRAME; 
 
  return (CAN_push (ctrl, msg, timeout)); 
} 
 
 
/*--------------------------- CAN_request ----------------------------------- 
 * 
 *  Send REMOTE FRAME message, see CAN_push function comment 
 * 
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x) 
 *              msg:        Pointer to CAN message to be sent 
 *              timeout:    Timeout value for message sending 
 * 
 *  Return:     CAN_ERROR:  Error code 
 *---------------------------------------------------------------------------*/ 
 
CAN_ERROR CAN_request (U32 ctrl, CAN_msg *msg, U16 timeout)  { 
  msg->type = REMOTE_FRAME; 
 
  return (CAN_push (ctrl, msg, timeout)); 
} 
 
 
/*--------------------------- CAN_set --------------------------------------- 
 * 
 *  Set a message that will automatically be sent as an answer to REMOTE 
 *  FRAME message 
 * 
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x) 
 *              msg:        Pointer to CAN message to be set 
 *              timeout:    Timeout value for message to be set 
 * 
 *  Return:     CAN_ERROR:  Error code 
 *---------------------------------------------------------------------------*/ 
 
CAN_ERROR CAN_set (U32 ctrl, CAN_msg *msg, U16 timeout)  { 
  S32 i = timeout; 
  U32 result = 0; 
 
  do { 
    if (CAN_hw_tx_empty (ctrl) == CAN_OK)  {  /* Transmit hardware free      */ 
      result = CAN_hw_set (ctrl, msg);  /* Set message                       */ 
      os_sem_send (wr_sem[ctrl-1]);     /* Return a token back to semaphore  */ 
      return CAN_OK; 
    } 
    if (timeout == 0xffff)              /* Indefinite wait                   */ 
      i++; 
    i--; 
    os_dly_wait (1);                    /* Wait 1 timer tick                 */ 
  }  while (i >= 0); 
 
  return CAN_TIMEOUT_ERROR;             /* CAN message not set               */ 
} 
 
 
/*--------------------------- CAN_pull -------------------------------------- 
 * 
 *  Pull first received and unread CAN_msg from receiving message queue 
 * 
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x) 
 *              msg:        Pointer where CAN message will be read 
 *              timeout:    Timeout value for message receiving 
 * 
 *  Return:     CAN_ERROR:  Error code 
 *---------------------------------------------------------------------------*/ 
 
 
static CAN_ERROR CAN_pull (U32 ctrl, CAN_msg *msg, U16 timeout)  { 
  CAN_msg *ptrmsg; 
  U32 ctrl0 = ctrl-1;                 /* Controller index 0 .. x-1           */ 
 
  /* Wait for received message in mailbox                                    */ 
  if (os_mbx_wait (MBX_rx_ctrl[ctrl0], (void **)&ptrmsg, timeout) == OS_R_TMO) 
    return CAN_TIMEOUT_ERROR; 
 
  /* Copy received message from mailbox to address given in function parameter msg */ 
  *msg = *ptrmsg; 
 
  /* Free box where message was kept                                         */ 
  if (_free_box (CAN_mpool, ptrmsg) == 1) 
    return CAN_DEALLOC_MEM_ERROR; 
 
  return CAN_OK; 
} 
 
 
/*--------------------------- CAN_receive ----------------------------------- 
 * 
 *  Read received message, see CAN_pull function comment 
 * 
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x) 
 *              msg:        Pointer where CAN message will be read 
 *              timeout:    Timeout value for message receiving 
 * 
 *  Return:     CAN_ERROR:  Error code 
 *---------------------------------------------------------------------------*/ 
 
CAN_ERROR CAN_receive (U32 ctrl, CAN_msg *msg, U16 timeout)  { 
  return (CAN_pull (ctrl, msg, timeout)); 
} 
 
 
/*--------------------------- CAN_rx_object --------------------------------- 
 * 
 *  Enable reception of messages on specified controller and channel with  
 *  specified identifier 
 * 
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x) 
 *              ch:         Channel for the message transmission 
 *              id:         CAN message identifier 
 *              CAN_FORMAT: Format of CAN identifier (standard or extended) 
 * 
 *  Return:     CAN_ERROR:  Error code 
 *---------------------------------------------------------------------------*/ 
 
CAN_ERROR CAN_rx_object (U32 ctrl, U32 ch, U32 id, CAN_FORMAT format)  { 
  return (CAN_hw_rx_object (ctrl, ch, id, format)); 
} 
 
 
/*--------------------------- CAN_tx_object --------------------------------- 
 * 
 *  Enable transmission of messages on specified controller and channel with  
 *  specified identifier 
 * 
 *  Parameter:  ctrl:       Index of the hardware CAN controller (1 .. x) 
 *              ch:         Channel for the message transmission 
 *              CAN_FORMAT: Format of CAN identifier (standard or extended) 
 * 
 *  Return:     CAN_ERROR:  Error code 
 *---------------------------------------------------------------------------*/ 
 
CAN_ERROR CAN_tx_object (U32 ctrl, U32 ch, CAN_FORMAT format)  { 
  return (CAN_hw_tx_object (ctrl, ch, format)); 
} 
 
 
/*---------------------------------------------------------------------------- 
 * end of file 
 *---------------------------------------------------------------------------*/