CAN_ERROR CAN_hw_wr (U32 ctrl, CAN_msg *msg) { uint8_t i; CAN_HandleTypeDef *hCAN; switch (ctrl) { #if RTE_CAN1 == 1 case __CTRL1: hCAN = &hCAN1; break; #endif #if RTE_CAN2 == 1 case __CTRL2: hCAN= &hCan2; break; #endif default: return CAN_UNEXIST_CTRL_ERROR; } hCAN->pTxMsg->DLC = msg->len; for(i=0;i<msg->len;++i) hCAN->pTxMsg->Data[i] = msg->data[i]; hCAN->pTxMsg->RTR = (msg->type == REMOTE_FRAME) ? CAN_RTR_REMOTE : CAN_RTR_DATA; if (msg->format==EXTENDED_FORMAT) { hCAN->pTxMsg->IDE = CAN_ID_EXT; hCAN->pTxMsg->ExtId = msg->id & 0x1fffffff; } else { hCAN->pTxMsg->IDE = CAN_ID_STD; hCAN->pTxMsg->StdId = msg->id & 0x7ff; } HAL_StatusTypeDef result = HAL_CAN_Transmit_IT(hCAN); while (result == HAL_TIMEOUT) { osDelay(5); result = HAL_CAN_Transmit_IT(hCAN); } // if (HAL_CAN_Transmit_IT(hCAN) != HAL_OK) if (result != HAL_OK) return CAN_TX_BUSY_ERROR; return CAN_OK; }
/** * @brief Set the settings of the CAN1 channel * @param MessageId: The message to transmit * @param pData: Pointer to the data to transmit * @param DataLength: Length of the data to transmit, can be any value of CANDataLength * @param Timeout: Timeout when we should stop trying to send if the CAN is busy * @retval None */ ErrorStatus can1Transmit(uint32_t MessageId, uint8_t* pData, CANDataLength DataLength, uint32_t Timeout) { /* Save the message ID */ if (prvCurrentSettings.identifier == CANIdentifier_Standard && MessageId <= 0x7FF) { CAN_Handle.pTxMsg->StdId = MessageId; CAN_Handle.pTxMsg->ExtId = 0x0; CAN_Handle.pTxMsg->IDE = CAN_ID_STD; } else if (prvCurrentSettings.identifier == CANIdentifier_Extended && MessageId <= 0x1FFFFFFF) { CAN_Handle.pTxMsg->StdId = 0x0; CAN_Handle.pTxMsg->ExtId = MessageId; CAN_Handle.pTxMsg->IDE = CAN_ID_EXT; } else goto error; /* Data frame */ CAN_Handle.pTxMsg->RTR = CAN_RTR_DATA; /* Data length */ CAN_Handle.pTxMsg->DLC = DataLength; /* Save the data */ for (uint32_t i = 0; i < DataLength; i++) { CAN_Handle.pTxMsg->Data[i] = pData[i]; } /* Save the current time and keep trying to transmit until the timeout happens */ TickType_t currentTime = xTaskGetTickCount(); uint32_t RetryCount = 0; while (HAL_CAN_Transmit_IT(&CAN_Handle) != HAL_OK) { vTaskDelayUntil(¤tTime, 1 / portTICK_PERIOD_MS); RetryCount++; if (RetryCount >= Timeout) goto error; } /* Everything went OK */ return SUCCESS; error: /* Something went wrong */ return ERROR; }
_Bool CAN_init(void *data) { CAN_HandleTypeDef *handle = data; HAL_StatusTypeDef result = HAL_ERROR; const uint32_t baudRate = 125000; CAN_InitTypeDef ifaceParams = { HAL_RCC_GetPCLK1Freq()/(baudRate*(1+4+3)), //(CAN_SJW + CAN_BS1 + CAN_BS2) CAN_MODE_NORMAL, CAN_SJW_1TQ, CAN_BS1_4TQ, CAN_BS2_3TQ, .TTCM = DISABLE, .ABOM = DISABLE, .AWUM = DISABLE, .NART = DISABLE, .RFLM = DISABLE, .TXFP = DISABLE, }; CAN_FilterConfTypeDef filter = { 0, 0, 0, 0, CAN_FIFO0, 0, CAN_FILTERMODE_IDMASK, CAN_FILTERSCALE_32BIT, ENABLE, 0 }; if (handle) { free(handle->pRxMsg); free(handle->pTxMsg); handle->pRxMsg = NULL; handle->pTxMsg = NULL; memset(handle, 0, sizeof(*handle)); handle->Instance = CAN1; handle->Init = ifaceParams; result = HAL_CAN_Init(handle); if (result == HAL_OK) { HAL_CAN_ConfigFilter(handle, &filter); HAL_NVIC_EnableIRQ(CAN1_TX_IRQn); HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn); HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn); // HAL_NVIC_EnableIRQ(CAN1_SCE_IRQn); handle->pRxMsg = malloc(sizeof(*handle->pRxMsg)); result &= HAL_CAN_Receive_IT(handle, CAN_FIFO0); } s_can1Handle = handle; } return result == HAL_OK; } _Bool CAN_write(const CanMsg_t *data) { HAL_StatusTypeDef result = HAL_ERROR; static const size_t msgSize = sizeof(CanTxMsgTypeDef); if (!data) return false; CanTxMsgTypeDef txMsg = { data->id, data->id, data->isExtended ? CAN_ID_EXT : CAN_ID_STD, data->isRemoteFrame ? CAN_RTR_REMOTE : CAN_RTR_DATA, data->isRemoteFrame ? 0 : data->size > 8 ? 8 : data->size, }; do { if (!s_can1Handle) break; memcpy(txMsg.Data, data->buff, txMsg.DLC); free(s_can1Handle->pTxMsg); s_can1Handle->pTxMsg = malloc(msgSize); if (!s_can1Handle->pTxMsg) break; memcpy(s_can1Handle->pTxMsg, &txMsg, msgSize); result = HAL_CAN_Transmit_IT(s_can1Handle); } while (0); return result == HAL_OK; }