// // Created by cfif on 16.03.2024. // #include #include "CanSerialPortFrame.h" #include "memory.h" #include "at32f435_437_misc.h" static void vCanSerialPortFrameInitNVICEnable(can_type *CANx, uint8_t irqSubPriority) { nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); if (CANx == CAN1) { NVIC_EnableIRQ(CAN1_SE_IRQn); NVIC_EnableIRQ(CAN1_RX0_IRQn); NVIC_EnableIRQ(CAN1_RX1_IRQn); NVIC_SetPriority(CAN1_SE_IRQn, irqSubPriority); NVIC_SetPriority(CAN1_RX0_IRQn, irqSubPriority); NVIC_SetPriority(CAN1_RX1_IRQn, irqSubPriority); can_interrupt_enable(CAN1, CAN_RF0MIEN_INT, TRUE); // can_interrupt_enable(CAN1, CAN_RF0FIEN_INT, TRUE); // can_interrupt_enable(CAN1, CAN_RF0OIEN_INT, TRUE); can_interrupt_enable(CAN1, CAN_RF1MIEN_INT, TRUE); // can_interrupt_enable(CAN1, CAN_RF1FIEN_INT, TRUE); // can_interrupt_enable(CAN1, CAN_RF1OIEN_INT, TRUE); can_interrupt_enable(CAN1, CAN_ETRIEN_INT, TRUE); can_interrupt_enable(CAN1, CAN_EOIEN_INT, TRUE); } if (CANx == CAN2) { NVIC_EnableIRQ(CAN2_SE_IRQn); NVIC_EnableIRQ(CAN2_RX0_IRQn); NVIC_EnableIRQ(CAN2_RX1_IRQn); NVIC_SetPriority(CAN2_SE_IRQn, irqSubPriority); NVIC_SetPriority(CAN2_RX0_IRQn, irqSubPriority); NVIC_SetPriority(CAN2_RX1_IRQn, irqSubPriority); can_interrupt_enable(CAN2, CAN_RF0MIEN_INT, TRUE); // can_interrupt_enable(CAN2, CAN_RF0FIEN_INT, TRUE); // can_interrupt_enable(CAN2, CAN_RF0OIEN_INT, TRUE); can_interrupt_enable(CAN2, CAN_RF1MIEN_INT, TRUE); // can_interrupt_enable(CAN2, CAN_RF1FIEN_INT, TRUE); // can_interrupt_enable(CAN2, CAN_RF1OIEN_INT, TRUE); can_interrupt_enable(CAN2, CAN_ETRIEN_INT, TRUE); can_interrupt_enable(CAN2, CAN_EOIEN_INT, TRUE); } } void CanSerialPortFrameSetId(tCanSerialPortFrameArtery *env, uint32_t id) { env->id = id; } void CanSerialPortFrameSetId1(tCanSerialPortFrameArtery *env, uint32_t id) { env->id1 = id; } void CanSerialPortFrameSetType(tCanSerialPortFrameArtery *env, eCanTypeFrame canTypeFrame) { env->canTypeFrame = canTypeFrame; } static void vCanSerialPortFrameInitStructure( tCanSerialPortFrameArtery *env, can_type *CANx, uint32_t rxBufferLength0, uint32_t rxSnifferLength0, uint32_t rxBufferLength1, uint32_t rxSnifferLength1 ) { env->rxDataQueue0 = osMessageQueueNew(rxBufferLength0, sizeof(can_rx_message_type), NULL); if (rxSnifferLength0) { env->rxDataSnifferQueue0 = osMessageQueueNew(rxSnifferLength0, sizeof(can_rx_message_type), NULL); } else { env->rxDataSnifferQueue0 = 0; } env->rxDataQueue1 = osMessageQueueNew(rxBufferLength1, sizeof(can_rx_message_type), NULL); if (rxSnifferLength1) { env->rxDataSnifferQueue1 = osMessageQueueNew(rxSnifferLength1, sizeof(can_rx_message_type), NULL); } else { env->rxDataSnifferQueue1 = 0; } } void vCanSerialPortFrameInit( tCanSerialPortFrameArtery *env, can_type *CANx, eCanBaudRate canBaudRate, uint8_t irqSubPriority, eCanTypeFrame canTypeFrame, uint32_t canId, uint32_t rxBufferLength0, uint32_t rxSnifferLength0, uint32_t rxBufferLength1, uint32_t rxSnifferLength1 ) { env->can = CANx; if (!env->reInit) { env->reInit = true; vCanSerialPortFrameInitStructure(env, CANx, rxBufferLength0, rxSnifferLength0, rxBufferLength1, rxSnifferLength1); CanSerialPortFrameSetType(env, canTypeFrame); CanSerialPortFrameSetId(env, canId); env->canBaudRate = canBaudRate; } can_base_type can_base_struct; can_baudrate_type can_baudrate_struct; // can_filter_init_type can_filter_init_struct; // enable the can clock if (CANx == CAN1) crm_periph_clock_enable(CRM_CAN1_PERIPH_CLOCK, TRUE); if (CANx == CAN2) crm_periph_clock_enable(CRM_CAN2_PERIPH_CLOCK, TRUE); // can base init can_default_para_init(&can_base_struct); can_base_struct.mode_selection = CAN_MODE_COMMUNICATE; // can_base_struct.mode_selection = CAN_MODE_LOOPBACK; can_base_struct.ttc_enable = FALSE; can_base_struct.aebo_enable = TRUE; can_base_struct.aed_enable = TRUE; can_base_struct.prsf_enable = FALSE; can_base_struct.mdrsel_selection = CAN_DISCARDING_FIRST_RECEIVED; can_base_struct.mmssr_selection = CAN_SENDING_BY_ID; can_base_init(CANx, &can_base_struct); can_baudrate_struct.baudrate_div = 125; can_baudrate_struct.rsaw_size = CAN_RSAW_1TQ; can_baudrate_struct.bts1_size = CAN_BTS1_6TQ; can_baudrate_struct.bts2_size = CAN_BTS2_1TQ; if (canBaudRate == CAN_BAUD_RATE_1000K) { can_baudrate_struct.baudrate_div = 4; can_baudrate_struct.rsaw_size = CAN_RSAW_1TQ; can_baudrate_struct.bts1_size = CAN_BTS1_5TQ; can_baudrate_struct.bts2_size = CAN_BTS2_3TQ; } if (canBaudRate == CAN_BAUD_RATE_500K) { can_baudrate_struct.baudrate_div = 25; can_baudrate_struct.rsaw_size = CAN_RSAW_1TQ; can_baudrate_struct.bts1_size = CAN_BTS1_8TQ; can_baudrate_struct.bts2_size = CAN_BTS2_1TQ; } if (canBaudRate == CAN_BAUD_RATE_250K) { can_baudrate_struct.baudrate_div = 50; can_baudrate_struct.rsaw_size = CAN_RSAW_1TQ; can_baudrate_struct.bts1_size = CAN_BTS1_8TQ; can_baudrate_struct.bts2_size = CAN_BTS2_1TQ; } if (canBaudRate == CAN_BAUD_RATE_125K) { can_baudrate_struct.baudrate_div = 125; can_baudrate_struct.rsaw_size = CAN_RSAW_1TQ; can_baudrate_struct.bts1_size = CAN_BTS1_6TQ; can_baudrate_struct.bts2_size = CAN_BTS2_1TQ; } can_baudrate_set(CANx, &can_baudrate_struct); /* // can filter init can_filter_init_struct.filter_activate_enable = TRUE; can_filter_init_struct.filter_mode = CAN_FILTER_MODE_ID_MASK; can_filter_init_struct.filter_fifo = CAN_FILTER_FIFO0; can_filter_init_struct.filter_number = 0; can_filter_init_struct.filter_bit = CAN_FILTER_32BIT; can_filter_init_struct.filter_id_high = 0; can_filter_init_struct.filter_id_low = 0; can_filter_init_struct.filter_mask_high = 0; can_filter_init_struct.filter_mask_low = 0; can_filter_init(CANx, &can_filter_init_struct); */ can_filter_init(CANx, &env->can_filter0_init_struct); /* // can filter init can_filter_init_struct.filter_activate_enable = TRUE; can_filter_init_struct.filter_mode = CAN_FILTER_MODE_ID_MASK; can_filter_init_struct.filter_fifo = CAN_FILTER_FIFO1; can_filter_init_struct.filter_number = 1; can_filter_init_struct.filter_bit = CAN_FILTER_32BIT; can_filter_init_struct.filter_id_high = 0; can_filter_init_struct.filter_id_low = 0; can_filter_init_struct.filter_mask_high = 0; can_filter_init_struct.filter_mask_low = 0; can_filter_init(CANx, &can_filter_init_struct); */ can_filter_init(CANx, &env->can_filter1_init_struct); vCanSerialPortFrameInitNVICEnable(CANx, irqSubPriority); } void CanSerialPortFrameIrqRxProcessing0(tCanSerialPortFrameArtery *env) { can_rx_message_type rx_message_struct; // if (can_flag_get(env->can, CAN_RF0MN_FLAG) != RESET) { can_message_receive(env->can, CAN_RX_FIFO0, &rx_message_struct); osMessageQueuePut(env->rxDataQueue0, &rx_message_struct, 0x0, 0U); if (env->rxDataSnifferQueue0) { osMessageQueuePut(env->rxDataSnifferQueue0, &rx_message_struct, 0x0, 0U); } // } } void CanSerialPortFrameIrqRxProcessing1(tCanSerialPortFrameArtery *env) { can_rx_message_type rx_message_struct; // if (can_flag_get(env->can, CAN_RF1MN_FLAG) != RESET) { can_message_receive(env->can, CAN_RX_FIFO1, &rx_message_struct); osMessageQueuePut(env->rxDataQueue1, &rx_message_struct, 0x0, 0U); if (env->rxDataSnifferQueue1) { osMessageQueuePut(env->rxDataSnifferQueue1, &rx_message_struct, 0x0, 0U); } // } } static uint16_t vSerialPortFrameReceiveQueue( tCanSerialPortFrameArtery *env, uint8_t *data, uint16_t size, uint32_t timeout, osMessageQueueId_t queueId ) { uint16_t received = 0; if (timeout) { uint32_t endMs = SystemGetMs() + timeout; uint32_t leftMs; while (size && ((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { leftMs = endMs - SystemGetMs(); if (osMessageQueueGet(queueId, data, NULL, leftMs) == osOK) { --size; ++received; ++data; } } } else { while (size) { if (osMessageQueueGet(queueId, data, NULL, 0) == osOK) { --size; ++received; ++data; } else { return received; } } } return received; } static uint16_t vCanSerialPortFrameReceive0(tCanSerialPortFrameArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { return vSerialPortFrameReceiveQueue(env, data, size, timeout, env->rxDataQueue0); } static uint16_t vCanSerialPortFrameReceive1(tCanSerialPortFrameArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { return vSerialPortFrameReceiveQueue(env, data, size, timeout, env->rxDataQueue1); } static uint16_t vCanSerialPortFrameReceiveSniffer0(tCanSerialPortFrameArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { return env->rxDataSnifferQueue0 ? vSerialPortFrameReceiveQueue(env, data, size, timeout, env->rxDataSnifferQueue0) : 0; } static uint16_t vCanSerialPortFrameReceiveSniffer1(tCanSerialPortFrameArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { return env->rxDataSnifferQueue1 ? vSerialPortFrameReceiveQueue(env, data, size, timeout, env->rxDataSnifferQueue1) : 0; } uint8_t can_message_transmitExt(can_type *can_x, can_tx_message_type *tx_message_struct, can_tx_mailbox_num_type mailbox) { uint8_t transmit_mailbox = CAN_TX_STATUS_NO_EMPTY; if (mailbox == CAN_TX_MAILBOX0) { if (can_x->tsts_bit.tm0ef) { transmit_mailbox = CAN_TX_MAILBOX0; } else { transmit_mailbox = CAN_TX_STATUS_NO_EMPTY; } } if (mailbox == CAN_TX_MAILBOX1) { if (can_x->tsts_bit.tm1ef) { transmit_mailbox = CAN_TX_MAILBOX1; } else { transmit_mailbox = CAN_TX_STATUS_NO_EMPTY; } } if (mailbox == CAN_TX_MAILBOX2) { if (can_x->tsts_bit.tm2ef) { transmit_mailbox = CAN_TX_MAILBOX2; } else { transmit_mailbox = CAN_TX_STATUS_NO_EMPTY; } } /* if(can_x->tsts_bit.tm0ef) { transmit_mailbox = CAN_TX_MAILBOX0; } else if(can_x->tsts_bit.tm1ef) { transmit_mailbox = CAN_TX_MAILBOX1; } else if(can_x->tsts_bit.tm2ef) { transmit_mailbox = CAN_TX_MAILBOX2; } else { transmit_mailbox = CAN_TX_STATUS_NO_EMPTY; } */ if (transmit_mailbox != CAN_TX_STATUS_NO_EMPTY) { /* set up the id */ can_x->tx_mailbox[transmit_mailbox].tmi &= 0x00000001; can_x->tx_mailbox[transmit_mailbox].tmi_bit.tmidsel = tx_message_struct->id_type; switch (tx_message_struct->id_type) { case CAN_ID_STANDARD: can_x->tx_mailbox[transmit_mailbox].tmi_bit.tmsid = tx_message_struct->standard_id; break; case CAN_ID_EXTENDED: can_x->tx_mailbox[transmit_mailbox].tmi |= (tx_message_struct->extended_id << 3); break; default: break; } can_x->tx_mailbox[transmit_mailbox].tmi_bit.tmfrsel = tx_message_struct->frame_type; /* set up the dlc */ can_x->tx_mailbox[transmit_mailbox].tmc_bit.tmdtbl = (tx_message_struct->dlc & ((uint8_t) 0x0F)); /* set up the data field */ can_x->tx_mailbox[transmit_mailbox].tmdtl = (((uint32_t) tx_message_struct->data[3] << 24) | ((uint32_t) tx_message_struct->data[2] << 16) | ((uint32_t) tx_message_struct->data[1] << 8) | ((uint32_t) tx_message_struct->data[0])); can_x->tx_mailbox[transmit_mailbox].tmdth = (((uint32_t) tx_message_struct->data[7] << 24) | ((uint32_t) tx_message_struct->data[6] << 16) | ((uint32_t) tx_message_struct->data[5] << 8) | ((uint32_t) tx_message_struct->data[4])); /* request transmission */ can_x->tx_mailbox[transmit_mailbox].tmi_bit.tmsr = TRUE; } return transmit_mailbox; } /* uint16_t vCanSerialPortFrameTransmit(tCanSerialPortFrameArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { uint16_t sent = 0; uint32_t endMs = SystemGetMs() + timeout; uint16_t fullSize = size / 8; uint8_t tailSize = size % 8; uint8_t transmit_mailbox; can_tx_message_type TxMessage; if (env->canTypeFrame == CAN_STD_ID) { TxMessage.standard_id = env->id; TxMessage.extended_id = 0; TxMessage.id_type = CAN_ID_STANDARD; } if (env->canTypeFrame == CAN_EXT_ID) { TxMessage.standard_id = 0; TxMessage.extended_id = env->id; TxMessage.id_type = CAN_ID_EXTENDED; } TxMessage.frame_type = CAN_TFT_DATA; TxMessage.dlc = 8; while (size && ((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { uint16_t len = 0; for (uint16_t i = 0; i < fullSize; ++i) { memcpy(TxMessage.data, &data[len], 8); len += 8; transmit_mailbox = can_message_transmitExt(env->can, &TxMessage, CAN_TX_MAILBOX0); while (can_transmit_status_get(env->can, (can_tx_mailbox_num_type) transmit_mailbox) != CAN_TX_STATUS_SUCCESSFUL) { if (!((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { return sent; } // if ((can_flag_get(env->can, CAN_BOF_FLAG) != RESET) || // (can_flag_get(env->can, CAN_EPF_FLAG) != RESET) || // (can_flag_get(env->can, CAN_EAF_FLAG) != RESET)) { // return sent; // } } sent += 8; size -= 8; } if (tailSize) { TxMessage.dlc = tailSize; memcpy(TxMessage.data, &data[len], tailSize); transmit_mailbox = can_message_transmit(env->can, &TxMessage); can_transmit_status_type status = can_transmit_status_get(env->can, (can_tx_mailbox_num_type) transmit_mailbox); while (status != CAN_TX_STATUS_SUCCESSFUL) { status = can_transmit_status_get(env->can, (can_tx_mailbox_num_type) transmit_mailbox); if (!((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { return sent; } } sent += tailSize; size -= tailSize; } } return sent; } */ uint16_t vCanSerialPortFrameTransmit(tCanSerialPortFrameArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { uint16_t sent = 0; uint32_t endMs = SystemGetMs() + timeout; uint16_t fullSize = size / 8; uint8_t tailSize = size % 8; uint8_t transmit_mailbox; can_tx_message_type TxMessage; if (env->canTypeFrame == CAN_STD_ID) { TxMessage.standard_id = env->id; TxMessage.extended_id = 0; TxMessage.id_type = CAN_ID_STANDARD; } if (env->canTypeFrame == CAN_EXT_ID) { TxMessage.standard_id = 0; TxMessage.extended_id = env->id; TxMessage.id_type = CAN_ID_EXTENDED; } TxMessage.frame_type = CAN_TFT_DATA; TxMessage.dlc = 8; while (size && ((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { uint16_t len = 0; for (uint16_t i = 0; i < fullSize; ++i) { memcpy(TxMessage.data, &data[len], 8); len += 8; transmit_mailbox = can_message_transmitExt(env->can, &TxMessage, CAN_TX_MAILBOX0); while (can_transmit_status_get(env->can, (can_tx_mailbox_num_type) transmit_mailbox) != CAN_TX_STATUS_SUCCESSFUL) { if (!((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { return sent; } // if ((can_flag_get(env->can, CAN_BOF_FLAG) != RESET) || // (can_flag_get(env->can, CAN_EPF_FLAG) != RESET) || // (can_flag_get(env->can, CAN_EAF_FLAG) != RESET)) { // return sent; // } } sent += 8; size -= 8; } if (tailSize) { TxMessage.dlc = tailSize; memcpy(TxMessage.data, &data[len], tailSize); transmit_mailbox = can_message_transmitExt(env->can, &TxMessage, CAN_TX_MAILBOX0); can_transmit_status_type status = can_transmit_status_get(env->can, (can_tx_mailbox_num_type) transmit_mailbox); while (status != CAN_TX_STATUS_SUCCESSFUL) { status = can_transmit_status_get(env->can, (can_tx_mailbox_num_type) transmit_mailbox); if (!((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { return sent; } } sent += tailSize; size -= tailSize; } } return sent; } uint16_t vCanSerialPortFrameTransmit1(tCanSerialPortFrameArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) { uint16_t sent = 0; uint32_t endMs = SystemGetMs() + timeout; uint16_t fullSize = size / 8; uint8_t tailSize = size % 8; uint8_t transmit_mailbox; can_tx_message_type TxMessage; if (env->canTypeFrame == CAN_STD_ID) { TxMessage.standard_id = env->id1; TxMessage.extended_id = 0; TxMessage.id_type = CAN_ID_STANDARD; } if (env->canTypeFrame == CAN_EXT_ID) { TxMessage.standard_id = 0; TxMessage.extended_id = env->id1; TxMessage.id_type = CAN_ID_EXTENDED; } TxMessage.frame_type = CAN_TFT_DATA; TxMessage.dlc = 8; while (size && ((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { uint16_t len = 0; for (uint16_t i = 0; i < fullSize; ++i) { memcpy(TxMessage.data, &data[len], 8); len += 8; transmit_mailbox = can_message_transmitExt(env->can, &TxMessage, CAN_TX_MAILBOX1); while (can_transmit_status_get(env->can, (can_tx_mailbox_num_type) transmit_mailbox) != CAN_TX_STATUS_SUCCESSFUL) { if (!((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { return sent; } // if ((can_flag_get(env->can, CAN_BOF_FLAG) != RESET) || // (can_flag_get(env->can, CAN_EPF_FLAG) != RESET) || // (can_flag_get(env->can, CAN_EAF_FLAG) != RESET)) { // return sent; // } } sent += 8; size -= 8; } if (tailSize) { TxMessage.dlc = tailSize; memcpy(TxMessage.data, &data[len], tailSize); transmit_mailbox = can_message_transmitExt(env->can, &TxMessage, CAN_TX_MAILBOX1); can_transmit_status_type status = can_transmit_status_get(env->can, (can_tx_mailbox_num_type) transmit_mailbox); while (status != CAN_TX_STATUS_SUCCESSFUL) { status = can_transmit_status_get(env->can, (can_tx_mailbox_num_type) transmit_mailbox); if (!((timeout == SystemWaitForever) || (endMs > SystemGetMs()))) { return sent; } } sent += tailSize; size -= tailSize; } } return sent; } tSerialPortFrameIO CanPortFrame_GetIo(tCanSerialPortFrameArtery *env) { tSerialPortFrameIO io = { .env = env, .receive0 = (SerialPortFrameIOTransaction) vCanSerialPortFrameReceive0, .receive1 = (SerialPortFrameIOTransaction) vCanSerialPortFrameReceive1, .transmit = (SerialPortFrameIOTransaction) vCanSerialPortFrameTransmit, .transmit1 = (SerialPortFrameIOTransaction) vCanSerialPortFrameTransmit1 }; return io; } tSerialPortFrameIO CanPort_GetSnifferIo(tCanSerialPortFrameArtery *env) { tSerialPortFrameIO io = { .env = env, .receive0 = (SerialPortFrameIOTransaction) vCanSerialPortFrameReceiveSniffer0, .receive1 = (SerialPortFrameIOTransaction) vCanSerialPortFrameReceiveSniffer1, .transmit = (SerialPortFrameIOTransaction) vCanSerialPortFrameTransmit, .transmit1 = (SerialPortFrameIOTransaction) vCanSerialPortFrameTransmit1 }; return io; }