// it runs with interrupts disabled, it is safe to set and use MOB
void DeviceCAN_AT90CAN::implTransmit(void)
  {
    if ((CANGSTA & _BV(TXBSY)) == 0)
      {
        Can_set_mob(NB_MOB_TX);
        CANSTMOB |= _BV(TXOK); // trigger transmit interrupt
      }
  }
//------------------------------------------------------------------------------
//  @fn can_get_status
//!
//! This function allows to return if the command has been performed or not.
//! In an reception case, all the CAN message is stored in the structure.
//! This function also updates the CAN descriptor status (MOB_TX_COMPLETED,
//!  MOB_RX_COMPLETED, MOB_RX_COMPLETED_DLCW or MOB_???_ERROR).
//!
//! @param  st_cmd_t* pointer on CAN descriptor structure.
//!
//! @return CAN_STATUS_COMPLETED     - Rx or Tx is completed
//!         CAN_STATUS_NOT_COMPLETED - Rx or Tx is not completed
//!         CAN_STATUS_ERROR         - Error in configuration or in the
//!                                    CAN communication
//!
//------------------------------------------------------------------------------
U8 can_get_status (st_cmd_t* cmd)
{
U8 a_status;
U8 rtn_val;

    a_status = cmd->status;
    if ( (a_status==STATUS_CLEARED)||(a_status==MOB_NOT_REACHED)||(a_status==MOB_DISABLE) )
    {
        return CAN_STATUS_ERROR;
    }

    Can_set_mob(cmd->handle);
    a_status = can_get_mob_status();

    switch (a_status)
    {
        case MOB_NOT_COMPLETED:
            // cmd->status not updated
            rtn_val = CAN_STATUS_NOT_COMPLETED;
            break;
        //--------------- special for "reduced_can_lib.c"
        case MOB_RX_COMPLETED:
        case MOB_RX_COMPLETED_DLCW:
            cmd->dlc = Can_get_dlc();
            can_get_data(cmd->pt_data);
            // Always standard frame
            Can_get_std_id(cmd->id.std);    //- Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement
            // Status field of descriptor: 0x20 if Rx completed
            // Status field of descriptor: 0xA0 if Rx completed with DLCWarning
            cmd->status = a_status;
            Can_mob_abort();        // Freed the MOB
            Can_clear_status_mob(); //   and reset MOb status
            rtn_val = CAN_STATUS_COMPLETED;
            break;
        //--------------- special for "reduced_can_lib.c"
        case MOB_TX_COMPLETED:
            // Status field of descriptor: 0x40 if Tx completed
            cmd->status = a_status;
            Can_mob_abort();        // Freed the MOB
            Can_clear_status_mob(); //   and reset MOb status
            rtn_val = CAN_STATUS_COMPLETED;
            break;
        //---------------
        default:
            // Status field of descriptor: (bin)000b.scfa if MOb error
            cmd->status = a_status;
            Can_mob_abort();        // Freed the MOB
            Can_clear_status_mob(); //   and reset MOb status
            rtn_val = CAN_STATUS_ERROR;
            break;
    }

    return (rtn_val);
}
//------------------------------------------------------------------------------
//  @fn can_cmd
//!
//! This function takes a CAN descriptor, analyses the action to do:
//! transmit, receive or abort.
//! This function returns a status (CAN_CMD_ACCEPTED or CAN_CMD_REFUSED) if
//! a MOb for Rx or Tx has been found. If no MOB has been found, the
//! application must be retry at a later date.
//! This function also updates the CAN descriptor status (MOB_PENDING or
//! MOB_NOT_REACHED) if a MOb for Rx or Tx has been found. If aborting
//! is performed, the CAN descriptor status will be set to STATUS_CLEARED.
//!
//! @param  st_cmd_t* - Can_descriptor pointer on CAN descriptor structure
//!         to select the action to do.
//!
//! @return CAN_CMD_ACCEPTED - command is accepted
//!         CAN_CMD_REFUSED  - command is refused
//!
//------------------------------------------------------------------------------
U8 can_cmd(st_cmd_t* cmd)
{
U8  cpt;
U8  rtn_val;
    rtn_val = CAN_CMD_ACCEPTED;
    cmd->status = MOB_PENDING;
// MH **************************************************************************************************************************************
    //------------ special for "reduced_can_lib.c"
    if ((cmd->cmd) == CMD_TX_DATA)
    {
	        cmd->handle = MOB_4;
	        Can_set_mob(MOB_4);

    //    cmd->handle = MOB_14;
     //   Can_set_mob(MOB_14);
        Can_clear_mob();
        Can_clear_ide();
        Can_set_std_id(cmd->id.std);
        for (cpt=0; cpt<cmd->dlc; cpt++) CANMSG = *(cmd->pt_data + cpt);
        Can_clear_rtr();
        Can_set_dlc(cmd->dlc);
        Can_config_tx();
    }
    //------------ special for "reduced_can_lib.c"
    else if ((cmd->cmd) == CMD_RX_DATA_MASKED)
    {
        cmd->handle = MOB_0;
        Can_set_mob(MOB_0);
        Can_clear_mob();
        Can_clear_ide();
        Can_set_std_id(cmd->id.std);
        Can_set_std_msk(cmd->msk.std);
        Can_set_rtrmsk(); Can_clear_rtr();
        Can_set_idemsk();
        Can_config_rx();
    }
    // case CMD_NONE or not implemented command
    else rtn_val= CAN_CMD_REFUSED;

    return rtn_val;
}
void DeviceCAN_AT90CAN::implInit(unsigned char mode)
  {
    OSDeviceDebug::putString_P(PSTR("DeviceCAN_AT90CAN::implInit()"));
    OSDeviceDebug::putNewLine();

    transceiverInit();

    Can_reset();

    interruptInit(); // must be after reset()

    /* CAN_KING setting */
    /* 125K, 75%, Tq=0.5uS, Tbit=16*Tq=8uS */
    /* Tprs=7*Tq, Tph1=4*Tq, Tph2=4*Tq, Tsjw=1*Tq */
    CANBT1 = 0x0E; /* 125K@16MHz */
    CANBT2 = 0x0C;
    CANBT3 = 0x37;

    can_clear_all_mob();

    // enable reception on the reception mob
    Can_set_mob(NB_MOB_RX);
    Can_config_rx();

    // enable both RX and TX mobs
    CANEN2 = _BV(NB_MOB_RX) | _BV(NB_MOB_TX);

    // enable interrupts for both RX and TX mobs
    CANIE2 = _BV(NB_MOB_RX) | _BV(NB_MOB_TX);

    mode = mode; // set to given mode
    Can_enable();

    transceiverHighSpeed();

    //OSDebugLed2::init();

    interruptEnable();

    m_isConnected = true;
  }
//------------------------------------------------------------------------------
//  @fn can_cmd
//!
//! This function takes a CAN descriptor, analyses the action to do:
//! transmit, receive or abort.
//! This function returns a status (CAN_CMD_ACCEPTED or CAN_CMD_REFUSED) if
//! a MOb for Rx or Tx has been found. If no MOB has been found, the
//! application must be retry at a later date.
//! This function also updates the CAN descriptor status (MOB_PENDING or
//! MOB_NOT_REACHED) if a MOb for Rx or Tx has been found. If aborting
//! is performed, the CAN descriptor status will be set to STATUS_CLEARED.
//!
//! @param  st_cmd_t* - Can_descriptor pointer on CAN descriptor structure
//!         to select the action to do.
//!
//! @return CAN_CMD_ACCEPTED - command is accepted
//!         CAN_CMD_REFUSED  - command is refused
//!
//------------------------------------------------------------------------------
U8 can_cmd(st_cmd_t* cmd)
{
  U8 mob_handle, cpt;
  U32 u32_temp;
  U16 tmp;
  
  if (cmd->cmd == CMD_ABORT)
  {
    if (cmd->status == MOB_PENDING)
    {
      // Rx or Tx not yet performed
      Can_set_mob(cmd->handle);
      Can_mob_abort();
      Can_clear_status_mob();       // To be sure !
      cmd->handle = 0;
    }
    cmd->status = STATUS_CLEARED; 
  }
  else
  {
    mob_handle = can_get_mob_free();
    if (mob_handle!= NO_MOB)
    {
      cmd->status = MOB_PENDING; 
      cmd->handle = mob_handle;
      Can_set_mob(mob_handle);
      Can_clear_mob();
          
      switch (cmd->cmd)
      {
        //------------      
        case CMD_TX:    
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          for (cpt=0;cpt<cmd->dlc;cpt++) CANMSG = *(cmd->pt_data + cpt);
          if (cmd->ctrl.rtr) Can_set_rtr(); 
            else Can_clear_rtr();    
          Can_set_dlc(cmd->dlc);
          Can_config_tx();
          break;
        //------------      
        case CMD_TX_DATA:    
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          for (cpt=0;cpt<cmd->dlc;cpt++) CANMSG = *(cmd->pt_data + cpt);
          cmd->ctrl.rtr=0; Can_clear_rtr();
          Can_set_dlc(cmd->dlc);
          Can_config_tx();
	  if(!cmd->blocking){	/* Enable interrupt */
        Can_set_mob_int(mob_handle) /* Ser ud til at virke */
		tIntReg = (CANIE1<<8) + CANIE2; /* test var */
	  }
          break;
        //------------      
        case CMD_TX_REMOTE:       
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          cmd->ctrl.rtr=1; Can_set_rtr();
          Can_set_dlc(cmd->dlc);
          Can_config_tx();
          break;
        //------------      
        case CMD_RX:
          u32_temp=0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          Can_clear_rtrmsk();
          Can_clear_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_RX_DATA:
          u32_temp=0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=0; Can_set_rtrmsk(); Can_clear_rtr();
          Can_clear_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_RX_REMOTE:
          u32_temp=0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=1; Can_set_rtrmsk(); Can_set_rtr();
          Can_clear_rplv();
          Can_clear_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_RX_MASKED:
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          u32_temp=~0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          Can_clear_rtrmsk();
          Can_set_idemsk();
          Can_config_rx();  
          break;
        //------------      
        case CMD_RX_DATA_MASKED:
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          u32_temp=~0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=0; Can_set_rtrmsk(); Can_clear_rtr();
          Can_set_idemsk();
          Can_config_rx();  
	Can_set_mob_int(mob_handle) /* Ser ud til at virke */          
          break;
        //------------      
        case CMD_RX_REMOTE_MASKED:
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          u32_temp=~0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=1; Can_set_rtrmsk(); Can_set_rtr();
          Can_clear_rplv();
          Can_set_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_REPLY:
          for (cpt=0;cpt<cmd->dlc;cpt++) CANMSG = *(cmd->pt_data + cpt);
          u32_temp=0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=1; Can_set_rtrmsk(); Can_set_rtr();
          Can_set_rplv();
          Can_clear_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_REPLY_MASKED:
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          for (cpt=0;cpt<cmd->dlc;cpt++) CANMSG = *(cmd->pt_data + cpt);
          u32_temp=~0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=1; Can_set_rtrmsk(); Can_set_rtr();
          Can_set_rplv();
          Can_set_idemsk();
          Can_config_rx();       
          break;
        //------------      
        default:
          // case CMD_NONE or not implemented command
          cmd->status = STATUS_CLEARED; 
          break;
        //------------      
      } // switch (cmd ...
    } // if (mob_handle ...
    else
    {
Exemple #6
0
//------------------------------------------------------------------------------
//  @fn can_cmd
//!
//! This function takes a CAN descriptor, analyses the action to do:
//! transmit, receive or abort.
//! This function returns a status (CAN_CMD_ACCEPTED or CAN_CMD_REFUSED) if
//! a MOb for Rx or Tx has been found. If no MOB has been found, the
//! application must be retry at a later date.
//! This function also updates the CAN descriptor status (MOB_PENDING or
//! MOB_NOT_REACHED) if a MOb for Rx or Tx has been found. If aborting
//! is performed, the CAN descriptor status will be set to STATUS_CLEARED.
//!
//! @param  st_cmd_t* - Can_descriptor pointer on CAN descriptor structure
//!         to select the action to do.
//!
//! @return CAN_CMD_ACCEPTED - command is accepted
//!         CAN_CMD_REFUSED  - command is refused
//!
//------------------------------------------------------------------------------
U8 can_cmd(st_cmd_t* cmd)
{
  U8 mob_handle, cpt;
  U32 u32_temp;
  
  if (cmd->cmd == CMD_ABORT)
  {
    if (cmd->status == MOB_PENDING)
    {
      // Rx or Tx not yet performed
      Can_set_mob(cmd->handle);
      Can_mob_abort();
      Can_clear_status_mob();       // To be sure !
      cmd->handle = 0;
    }
    cmd->status = STATUS_CLEARED; 
  }
  else
  {
    mob_handle = can_get_mob_free();
    if (mob_handle!= NO_MOB)
    {
      cmd->status = MOB_PENDING; 
      cmd->handle = mob_handle;
      Can_set_mob(mob_handle);
      Can_clear_mob();
          
      switch (cmd->cmd)
      {
        //------------      
        case CMD_TX:    
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          for (cpt=0;cpt<cmd->dlc;cpt++) CANMSG = *(cmd->pt_data + cpt);
          if (cmd->ctrl.rtr) Can_set_rtr(); 
            else Can_clear_rtr();    
          Can_set_dlc(cmd->dlc);
          Can_config_tx();
          break;
        //------------      
        case CMD_TX_DATA:    
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          for (cpt=0;cpt<cmd->dlc;cpt++) CANMSG = *(cmd->pt_data + cpt);
          cmd->ctrl.rtr=0; Can_clear_rtr();
          Can_set_dlc(cmd->dlc);
          Can_config_tx();
          break;
        //------------      
        case CMD_TX_REMOTE:       
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          cmd->ctrl.rtr=1; Can_set_rtr();
          Can_set_dlc(cmd->dlc);
          Can_config_tx();
          break;
        //------------      
        case CMD_RX:

		  u32_temp=~0; Can_set_ext_msk(u32_temp); // Änderung durch Muri Christian

		  //u32_temp=0; Can_set_ext_msk(u32_temp); //origianl
          Can_set_dlc(cmd->dlc);
          Can_clear_rtrmsk();
          Can_clear_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_RX_DATA:
		
		  if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}

		  u32_temp = ~0x00;	//Änderung durch Muri Christian
		  Can_set_ext_msk(u32_temp);	// 

          //u32_temp=~0; Can_set_ext_msk(u32_temp); //original
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=0; Can_set_rtrmsk(); Can_clear_rtr();
          Can_set_idemsk();
          Can_config_rx()    
          break;
        //------------      
        case CMD_RX_REMOTE:
          
		  u32_temp=~0; Can_set_ext_msk(u32_temp); // Änderung durch Muri Christian
		  
		  
		  //u32_temp=0; Can_set_ext_msk(u32_temp); //orginal
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=1; Can_set_rtrmsk(); Can_set_rtr();
          Can_clear_rplv();
          Can_clear_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_RX_MASKED:
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          
		  u32_temp = get_idmask(cmd);	//Änderung durch Muri Christian
		  Can_set_ext_msk(u32_temp);

		  //u32_temp=~0; Can_set_ext_msk(u32_temp); //origianl
          Can_set_dlc(cmd->dlc);
          Can_clear_rtrmsk();
          Can_set_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_RX_DATA_MASKED:
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}

		  u32_temp = get_idmask(cmd);	//Änderung durch Muri Christian
		  Can_set_ext_msk(u32_temp);	// 

          //u32_temp=~0; Can_set_ext_msk(u32_temp); //original
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=0; Can_set_rtrmsk(); Can_clear_rtr();
          Can_set_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_RX_REMOTE_MASKED:
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}

          u32_temp = get_idmask(cmd);	//Änderung durch Muri Christian
		  Can_set_ext_msk(u32_temp);

		  //u32_temp=~0; Can_set_ext_msk(u32_temp); //original
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=1; Can_set_rtrmsk(); Can_set_rtr();
          Can_clear_rplv();
          Can_set_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_REPLY:
          for (cpt=0;cpt<cmd->dlc;cpt++) CANMSG = *(cmd->pt_data + cpt);
          
		  u32_temp=~0; Can_set_ext_msk(u32_temp); // Änderung durch Muri Christian		  

		  //u32_temp=0; Can_set_ext_msk(u32_temp); //origianl
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=1; Can_set_rtrmsk(); Can_set_rtr();
          Can_set_rplv();
          Can_clear_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_REPLY_MASKED:
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          for (cpt=0;cpt<cmd->dlc;cpt++) CANMSG = *(cmd->pt_data + cpt);

          u32_temp = get_idmask(cmd);	//Änderung durch Muri Christian
		  Can_set_ext_msk(u32_temp);

		  //u32_temp=~0; Can_set_ext_msk(u32_temp); //original
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=1; Can_set_rtrmsk(); Can_set_rtr();
          Can_set_rplv();
          Can_set_idemsk();
          Can_config_rx();       
          break;
        //------------      
        default:
          // case CMD_NONE or not implemented command
          cmd->status = STATUS_CLEARED; 
          break;
        //------------      
      } // switch (cmd ...
    } // if (mob_handle ...
    else
    {
void DeviceCAN_AT90CAN::interruptServiceRoutine(void)
  {
    //OSDeviceDebug::putString(" IRQ ");

    unsigned char c;
    if ((CANGIT & _BV(CANIT)) != 0)
      {
        unsigned char c;
        c = CANSIT2 & CANIE2;

        // we currently use only two MOBs, one for TX and 
        // one for RX, no need to iterrate all
        if ((c & _BV(NB_MOB_TX)) != 0)
          {
            // MOB0, transmit
            Can_set_mob(NB_MOB_TX);

            c = CANSTMOB;
            if ((c & _BV(TXOK)) != 0)
              {
                // read-modify-write
                CANSTMOB &= ~_BV(TXOK);

                //OSDebugLed2::on();

                if (!m_txBuf.isEmpty())
                  {
                    CANPacket packet;
                    m_txBuf.get((unsigned char*)&packet);

                    Can_clear_mob(); // previous status saved in c

                      {
                        Can_set_std_id(packet.id);
                        for (unsigned char cpt = 0; cpt < packet.len; cpt++)
                          CANMSG = packet.data[cpt];
                        Can_clear_rtr();
                        Can_set_dlc(packet.len);
                      }
                    Can_config_tx(); // already cleared
                    //OSDeviceDebug::putString(" tx ");
                  }

                else
                  {
                    // nothing more to transmit
                    DISABLE_MOB();

                    // OSDeviceDebug::putString(" empty ");
                  }

                if (m_txBuf.isBelowLowWM())
                  OSScheduler::eventNotify(getWriteEvent());

                //OSDebugLed2::off();
              }
            else
              {
                // other interrupts...
                OSDeviceDebug::putString_P(PSTR(" CANSTMOB0="));
                OSDeviceDebug::putHex(c);
                OSDeviceDebug::putChar(' ');

                CANSTMOB = 0;
              }
          }

        if ((c & _BV(NB_MOB_RX)) != 0)
          {
            // MOB1, receive
            Can_set_mob(NB_MOB_RX);

            c = CANSTMOB;
            if ((c & _BV(RXOK)) != 0)
              {
                //OSDeviceDebug::putString(" rx ");
                if ((c & _BV(IDE)) == 0)
                  {
                    // standard 11 bits ID; reply bit ignored 
                    CANPacket can_packet;

                    can_packet.id = Can_get_std_id();
                    can_packet.len = Can_get_dlc();
                    can_get_data(can_packet.data);

#if 0
                    if (can_packet.id != 0)
                      {
                        can_packet.dump();
                      }
#endif

                    if (!m_rxBuf.isFull())
                      {
                        m_rxBuf.put((unsigned char*)&can_packet);
                      }

                    OSScheduler::eventNotify(getReadEvent());
                  }
                // re-enable reception on this mob
                Can_clear_mob();
                // DISABLE_MOB();
                Can_config_rx();

                //CANSTMOB = c & ~_BV(RXOK);
              }
            else
              {
                // other interrupts...
                OSDeviceDebug::putString_P(PSTR(" CANSTMOB1="));
                OSDeviceDebug::putHex(c);
                OSDeviceDebug::putChar(' ');

                CANSTMOB = 0;
              }
          }
      }

    c = CANGIT & ~(_BV(CANIT) | _BV(OVRTIM));
    if (c != 0)
      {
        // other interrupts...
        OSDeviceDebug::putString_P(PSTR(" CANGIT="));
        OSDeviceDebug::putHex(c);
        OSDeviceDebug::putChar(' ');

        // reset interrupt flag 
        CANGIT |= c;
      }
  }
//------------------------------------------------------------------------------
//  @fn can_get_status
//!
//! This function allows to return if the command has been performed or not.
//! In an reception case, all the CAN message is stored in the structure.
//! This function also updates the CAN descriptor status (MOB_TX_COMPLETED,    
//!  MOB_RX_COMPLETED, MOB_RX_COMPLETED_DLCW or MOB_???_ERROR).         
//!
//! @param  st_cmd_t* pointer on CAN descriptor structure.
//!
//! @return CAN_STATUS_COMPLETED     - Rx or Tx is completed
//!         CAN_STATUS_NOT_COMPLETED - Rx or Tx is not completed
//!         CAN_STATUS_ERROR         - Error in configuration or in the
//!                                    CAN communication
//!
//------------------------------------------------------------------------------
U8 can_get_status (st_cmd_t* cmd)
{
    U8 a_status, rtn_val;
     
    a_status = cmd->status;
    if ((a_status==STATUS_CLEARED)||(a_status==MOB_NOT_REACHED)||(a_status==MOB_DISABLE))
    {
        return CAN_STATUS_ERROR;
    }

    Can_set_mob(cmd->handle);
    a_status = can_get_mob_status();
    
    switch (a_status)
    {
        case MOB_NOT_COMPLETED:
            // cmd->status not updated
            rtn_val = CAN_STATUS_NOT_COMPLETED;
            break;
        //---------------      
        case MOB_RX_COMPLETED:     
        case MOB_RX_COMPLETED_DLCW:
            cmd->dlc = Can_get_dlc();
            can_get_data(cmd->pt_data);
            cmd->ctrl.rtr = Can_get_rtr();
            if (Can_get_ide()) // if extended frame
            {
                cmd->ctrl.ide = 1; // extended frame
                Can_get_ext_id(cmd->id.ext);
            }
            else // else standard frame
                {
                    cmd->ctrl.ide = 0;
                    Can_get_std_id(cmd->id.std);
                }
            // Status field of descriptor: 0x20 if Rx completed
            // Status field of descriptor: 0xA0 if Rx completed with DLCWarning    
            cmd->status = a_status;
            Can_mob_abort();        // Freed the MOB
            Can_clear_status_mob(); //   and reset MOb status
            rtn_val = CAN_STATUS_COMPLETED;
            break;
        //---------------      
        case MOB_TX_COMPLETED:     
            // Status field of descriptor: 0x40 if Tx completed
            cmd->status = a_status;
            Can_mob_abort();        // Freed the MOB
            Can_clear_status_mob(); //   and reset MOb status
            rtn_val = CAN_STATUS_COMPLETED;
            break;
        //---------------      
        default:
            // Status field of descriptor: (bin)000b.scfa if MOb error
            cmd->status = a_status;
            Can_mob_abort();        // Freed the MOB
            Can_clear_status_mob(); //   and reset MOb status
            rtn_val = CAN_STATUS_ERROR;
            break;
             
    } // switch (a_status...
 
    return (rtn_val);
}
Exemple #9
0
//------------------------------------------------------------------------------
//  @fn can_cmd
//!
//! This function takes a CAN descriptor, analyses the action to do:
//! transmit, receive or abort.
//! This function returns a status (CAN_CMD_ACCEPTED or CAN_CMD_REFUSED) if
//! a MOb for Rx or Tx has been found. If no MOB has been found, the
//! application must be retry at a later date.
//! This function also updates the CAN descriptor status (MOB_PENDING or
//! MOB_NOT_REACHED) if a MOb for Rx or Tx has been found. If aborting
//! is performed, the CAN descriptor status will be set to STATUS_CLEARED.
//!
//! @param  st_cmd_t* - Can_descriptor pointer on CAN descriptor structure
//!         to select the action to do.
//!
//! @return CAN_CMD_ACCEPTED - command is accepted
//!         CAN_CMD_REFUSED  - command is refused
//!
//------------------------------------------------------------------------------
U8 can_cmd(st_cmd_t* cmd)
{
  U8 mob_handle, cpt;
  U32 u32_temp;
  
  if (cmd->cmd == CMD_ABORT)
  {
    if (cmd->status == MOB_PENDING)
    {
      // Rx or Tx not yet performed
      Can_set_mob(cmd->handle);
      Can_mob_abort();
      Can_clear_status_mob();       // To be sure !
      cmd->handle = 0;
    }
    cmd->status = STATUS_CLEARED; 
  }
  else
  {
    mob_handle = can_get_mob_free();
    if (mob_handle!= NO_MOB)
    {
      cmd->status = MOB_PENDING; 
      cmd->handle = mob_handle;
      Can_set_mob(mob_handle);
      Can_clear_mob();
          
      switch (cmd->cmd)
      {
	  	//------------      
        case CMD_TX_DATA:    
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          for (cpt=0;cpt<cmd->dlc;cpt++) CANMSG = *(cmd->pt_data + cpt);
          cmd->ctrl.rtr=0; Can_clear_rtr();
          Can_set_dlc(cmd->dlc);
          Can_config_tx();
          break;
	  	//------------ 
		case CMD_RX_DATA_DEFINED_MASK://To use different masks. Added by Laszlo Kis
		  if (cmd->ctrl.ide){
		  	Can_set_ext_id(cmd->id.ext);
		  	u32_temp=cmd->id_mask.ext; 
			Can_set_ext_msk(u32_temp);		
		  	}
          else{ 
		  	Can_set_std_id(cmd->id.std);			
		  	u32_temp=cmd->id_mask.std; 
		  	Can_set_std_msk(u32_temp);
			}
          
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=0; Can_set_rtrmsk(); Can_clear_rtr();
          Can_set_idemsk();
          Can_config_rx();       
          break;        
        //------------      
        case CMD_TX:    
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          for (cpt=0;cpt<cmd->dlc;cpt++) CANMSG = *(cmd->pt_data + cpt);
          if (cmd->ctrl.rtr) Can_set_rtr(); 
            else Can_clear_rtr();    
          Can_set_dlc(cmd->dlc);
          Can_config_tx();
          break;
        //------------      
        case CMD_TX_REMOTE:       
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          cmd->ctrl.rtr=1; Can_set_rtr();
          Can_set_dlc(cmd->dlc);
          Can_config_tx();
          break;
        //------------      
        case CMD_RX:
          u32_temp=0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          Can_clear_rtrmsk();
          Can_clear_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_RX_DATA:
          u32_temp=0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=0; Can_set_rtrmsk(); Can_clear_rtr();
          Can_clear_idemsk();
          Can_config_rx();       
          break;
        //------------
		    
        case CMD_RX_REMOTE:
          u32_temp=0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=1; Can_set_rtrmsk(); Can_set_rtr();
          Can_clear_rplv();
          Can_clear_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_RX_MASKED:
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          u32_temp=~0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          Can_clear_rtrmsk();
          Can_set_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_RX_DATA_MASKED:
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          u32_temp=~0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=0; Can_set_rtrmsk(); Can_clear_rtr();
          Can_set_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_RX_REMOTE_MASKED:
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          u32_temp=~0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=1; Can_set_rtrmsk(); Can_set_rtr();
          Can_clear_rplv();
          Can_set_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_REPLY:
          for (cpt=0;cpt<cmd->dlc;cpt++) CANMSG = *(cmd->pt_data + cpt);
          u32_temp=0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=1; Can_set_rtrmsk(); Can_set_rtr();
          Can_set_rplv();
          Can_clear_idemsk();
          Can_config_rx();       
          break;
        //------------      
        case CMD_REPLY_MASKED:
          if (cmd->ctrl.ide){ Can_set_ext_id(cmd->id.ext);}
          else              { Can_set_std_id(cmd->id.std);}
          for (cpt=0;cpt<cmd->dlc;cpt++) CANMSG = *(cmd->pt_data + cpt);
          u32_temp=~0; Can_set_ext_msk(u32_temp);
          Can_set_dlc(cmd->dlc);
          cmd->ctrl.rtr=1; Can_set_rtrmsk(); Can_set_rtr();
          Can_set_rplv();
          Can_set_idemsk();
          Can_config_rx();       
          break;
        //------------      
        default:
          // case CMD_NONE or not implemented command
          cmd->status = STATUS_CLEARED; 
          break;
        //------------      
      } // switch (cmd ...
    } // if (mob_handle ...
    else
    {
      cmd->status = MOB_NOT_REACHED;
      return CAN_CMD_REFUSED;
    }
  } // else of no CMD_ABORT
  return CAN_CMD_ACCEPTED;
}