Beispiel #1
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;
            }
        }
    }
}