//------------------------------------------------------------------------------ // @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); }
static void int_handler(uint16_t source) { uint8_t mob_handle; can_cmd_t * cmd; mob_handle = 0; while(source != 0) { if(source & 1) { cmd = can_mob[mob_handle]; if(cmd != NULL) { CAN_SET_MOB(mob_handle); cmd->status = CAN_GET_STATUS_MOB() ; // RX operation finished if(cmd->status & MOB_RX_COMPLETED_DLCW) { cmd->frame->data.len = CAN_GET_DLC(); can_get_data(cmd->frame->data.itself); cmd->frame->inf.rtr = CAN_GET_RTR(); if (CAN_GET_IDE()) { cmd->frame->inf.ide = 1; CAN_GET_EXT_ID(cmd->frame->inf.id); } else { cmd->frame->inf.ide = 0; CAN_GET_STD_ID(cmd->frame->inf.id); } } } // reset MOb status CAN_CLEAR_STATUS_MOB(); } ++mob_handle; source >>= 1; } process_poll(&can_drv_process); }
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); }