示例#1
0
/** Find Oldest MOB
 * Searches the CAN timestamp and returns the
 * can-mob with the oldest timestamp.
 */
static inline uint8_t can_find_oldest_mob(void) {

	static uint8_t mob, mob_winner;
	static uint16_t mob_time;
	static uint32_t time;
	static uint16_t diff, diff_highest;

	diff_highest = 0;
	for (mob = 0; mob <= 14; mob++) {
		CAN_SET_MOB(mob);
		if (CANSTMOB) {
			time = CANTIMH << 8 | CANTIML;
			mob_time = CANSTMH << 8 | CANSTML;

			/* Check for overflow */
			if (mob_time > time) {
				diff = (time + 0xFFFF) - mob_time;				
			} else {
				diff = time - mob_time;
			}
			if (diff >= diff_highest) {
				mob_winner = mob;
				diff_highest = diff;
			}
		}
	}

	return mob_winner;

}
示例#2
0
int can_send(can_id_t id, uint8_t data[], uint8_t dlc, CSP_BASE_TYPE * task_woken) {

	int i, m = -1;

	/* Disable CAN interrupt while looping MOBs */
	CAN_CLEAR_INTERRUPT();

	/* Disable interrupts while looping mailboxes */
	if (task_woken == NULL) {
		portENTER_CRITICAL();
	}

	/* Search free MOB from 0 -> CAN_TX_MOBs */
	for(i = 0; i < CAN_TX_MOBS; i++) {
		if (mbox[i] == MBOX_FREE && !(CANEN2 & (1 << i))) {
			mbox[i] = MBOX_USED;
			m = i;
			break;
		}
	}
	
	/* Enable interrupts */
	if (task_woken == NULL) {
		portEXIT_CRITICAL();
	}

	/* Enable CAN interrupt */
	CAN_SET_INTERRUPT();

	/* Return if no available MOB was found */
	if (m < 0) {
		csp_log_warn("TX overflow, no available MOB\r\n");
		return -1;
	}

	/* Select and clear mob */
	CAN_SET_MOB(m);
	CAN_MOB_ABORT();
	CAN_CLEAR_STATUS_MOB();

	/* Set identifier */
	CAN_SET_EXT_ID(id);

	/* Set data - CANMSG is auto incrementing */
	for (i = 0; i < dlc; i++)
		CANMSG = data[i];

	/* Set DLC */
	CAN_CLEAR_DLC();
	CAN_SET_DLC(dlc);

	/* Start TX */
	CAN_CONFIG_TX();

	return 0;

}
PROCESS_THREAD(can_drv_process, ev, data) {
    static can_cmd_t * cmd;
    static uint8_t mob_handle;
    uint8_t do_create_recv_buf = 0;

    PROCESS_BEGIN();

    for(;;) {
        // wait on polling or timer event
        PROCESS_WAIT_EVENT();

        // Post event about completed commands and free the mob
        for(mob_handle = 0; mob_handle < NB_MOB; ++mob_handle) {
            cmd = can_mob[mob_handle];
            do_create_recv_buf = 0;

            if(cmd != NULL) {
                if(cmd->status != MOB_PENDING) {
                    if(cmd->status & MOB_TX_COMPLETED) {
                        ftimer_unregister_func(cmd->ftimer_id);
                        can_send_callback(CAN_DRV_RC_NORM, cmd->frame, cmd->context);
                    } else if(cmd->status & MOB_RX_COMPLETED) {
                        can_recv_callback(cmd->frame);
                        do_create_recv_buf = 1;
                    }
                    can_mob[mob_handle] = NULL;
                    free(cmd);
                    CAN_SET_MOB(mob_handle);
                    CAN_MOB_ABORT();
                }
            }

            if(do_create_recv_buf) {
                create_recv_buf();
            }
        }

        // If waiting queue not empty, try to schedule waiting commands
        while( list_head(can_cmd_list) != 0 ) {
            if(can_get_mob_free() != NO_MOB) {
                cmd = list_pop(can_cmd_list);
                post_cmd(cmd);
            } else {
                break;
            }
        }
    }

    PROCESS_END();
}
static void abort_cmd(can_cmd_t * cmd) {
    uint8_t cpt;

    if(cmd == NULL) return;

    if(cmd->next != NULL) {
        // remove command from waiting queue
        list_remove(can_cmd_list, cmd);
    } else {
        // remove from pending table
        for(cpt = 0; cpt < NB_MOB; ++cpt) {
            if(cmd == can_mob[cpt])  {
                can_mob[cpt] = NULL;
                CAN_SET_MOB(cpt);
                CAN_MOB_ABORT();
                break;
            }
        }
    }
}
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);
}
示例#6
0
void can_configure_mobs(void) {

	int mob;

	/* Initialize MOBs */
	for (mob = 0; mob < CAN_MOBS; mob++) {
		/* Set MOB */
		CAN_SET_MOB(mob);
		CAN_CLEAR_MOB();

		/* Only RX mobs require special initialization */
		if (mob >= CAN_TX_MOBS) {
			/* Set id and mask */
			CAN_SET_EXT_ID(can_id);
			CAN_SET_EXT_MSK(can_mask);

			/* Accept extended frames */
			CAN_CLEAR_IDEMSK();
			CAN_CONFIG_RX();
		}

	}
}
static void post_cmd(can_cmd_t * cmd) {
    uint8_t mob_handle;
    uint8_t i;

    if(cmd == NULL) return;

    mob_handle = can_get_mob_free();

    // add command to wait queue if there are no free mobs
    if(mob_handle == NO_MOB) {
        cmd->status = MOB_NOT_COMPLETED;
        list_add(can_cmd_list, cmd);
    }
    // add command to table of pending command otherwise
    else {
        can_mob[mob_handle] = cmd;
        cmd->status = MOB_PENDING;
        CAN_SET_MOB(mob_handle);
        CAN_CLEAR_MOB();

        switch(cmd->type) {
            case TX:
                if(cmd->frame->inf.ide) {
                    CAN_SET_EXT_ID(cmd->frame->inf.id);
                } else {
                    CAN_SET_STD_ID(cmd->frame->inf.id);
                }

                for(i = 0; i < cmd->frame->data.len; ++i) {
                    CANMSG = cmd->frame->data.itself[i];
                }

                if(cmd->frame->inf.rtr) {
                    CAN_SET_RTR();
                } else {
                    CAN_CLEAR_RTR();
                }
                CAN_SET_DLC(cmd->frame->data.len);
                CAN_CONFIG_TX();
                break;

            case RX:
                if (cmd->frame->inf.ide) {
                    CAN_SET_EXT_ID(can_masked_id);
                    CAN_SET_IDEMSK();
                    CAN_SET_EXT_MSK(can_mask);
                } else {
                    CAN_SET_STD_ID(can_masked_id);
                    CAN_CLEAR_IDEMSK();
                    CAN_SET_STD_MSK(can_mask);
                }
                CAN_SET_DLC(cmd->frame->data.len);
                CAN_CLEAR_RTRMSK();
                CAN_CONFIG_RX();
                break;

            default:
                cmd->status = STATUS_CLEARED;
                break;
        }
    }
}