//------------------------------------------------------------------------------
//  @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);
}
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;
      }
  }
Exemplo n.º 3
0
//------------------------------------------------------------------------------
//  @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);
}