You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
296 lines
8.5 KiB
296 lines
8.5 KiB
#include "can_controller.h"
|
|
#include <cstring>
|
|
#include <main.h>
|
|
#include <base/zlog.h>
|
|
#define TAG "CAN"
|
|
|
|
#define CAN_MESSAGE_POOL_SIZE 20
|
|
// 使用 CMSIS - RTOS v2 的内存池句柄类型
|
|
osMemoryPoolId_t can_message_pool;
|
|
// 使用 CMSIS - RTOS v2 的信号量句柄类型
|
|
osSemaphoreId_t g_can_rx0_semaphore = NULL;
|
|
// 使用 CMSIS - RTOS v2 的消息队列句柄类型
|
|
osMessageQueueId_t g_can_rx0_queue = NULL;
|
|
|
|
CanMessage g_can_recv_msg;
|
|
|
|
CANSystemResourceManager canSystemResourceManager;
|
|
|
|
// 新的线程函数
|
|
void canMessageProcessingTask(void *argument) {
|
|
while (1) {
|
|
// 等待信号量
|
|
osSemaphoreAcquire(g_can_rx0_semaphore, osWaitForever);
|
|
|
|
CanMessage* msgPtr = (CanMessage*)osMemoryPoolAlloc(can_message_pool, osWaitForever);
|
|
if (msgPtr == NULL) {
|
|
continue;
|
|
}
|
|
|
|
msgPtr->id = g_can_recv_msg.id;
|
|
msgPtr->length = g_can_recv_msg.length;
|
|
memcpy(msgPtr->data, g_can_recv_msg.data, msgPtr->length);
|
|
#if 1
|
|
// 将消息放入接收队列
|
|
osStatus_t status = osMessageQueuePut(g_can_rx0_queue, &msgPtr, 0U, 0U);
|
|
if (status != osOK) {
|
|
osMemoryPoolFree(can_message_pool, msgPtr);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
CANSystemResourceManager::CANSystemResourceManager() {
|
|
// 初始化信号量
|
|
osSemaphoreAttr_t semaphore_attr = {0};
|
|
semaphore_attr.name = "g_can_rx0_semaphore";
|
|
g_can_rx0_semaphore = osSemaphoreNew(1, 1, &semaphore_attr);
|
|
if (g_can_rx0_semaphore == NULL) {
|
|
// 处理信号量创建失败的情况
|
|
}
|
|
|
|
// 创建对象池
|
|
osMemoryPoolAttr_t pool_attr = {0};
|
|
pool_attr.name = "can_message_pool";
|
|
can_message_pool = osMemoryPoolNew(CAN_MESSAGE_POOL_SIZE, sizeof(CanMessage), &pool_attr);
|
|
if (can_message_pool == NULL) {
|
|
// 处理对象池创建失败的情况
|
|
if (g_can_rx0_semaphore != NULL) {
|
|
osSemaphoreDelete(g_can_rx0_semaphore);
|
|
}
|
|
}
|
|
|
|
// 创建接收队列
|
|
osMessageQueueAttr_t queue_attr = {0};
|
|
queue_attr.name = "g_can_rx0_queue";
|
|
|
|
g_can_rx0_queue = osMessageQueueNew(20, sizeof(CanMessage*), &queue_attr);
|
|
if (g_can_rx0_queue == NULL) {
|
|
// 处理消息队列创建失败的情况
|
|
if (g_can_rx0_semaphore != NULL) {
|
|
osSemaphoreDelete(g_can_rx0_semaphore);
|
|
}
|
|
if (can_message_pool != NULL) {
|
|
osMemoryPoolDelete(can_message_pool);
|
|
}
|
|
}
|
|
|
|
// 创建 CAN 消息处理线程
|
|
osThreadAttr_t canProcessingTaskAttr = {0};
|
|
canProcessingTaskAttr.name = "CanMessageProcessingTask";
|
|
canProcessingTaskAttr.stack_size = 128 * 8;
|
|
canProcessingTaskAttr.priority = osPriorityNormal;
|
|
osThreadNew(canMessageProcessingTask, NULL, &canProcessingTaskAttr);
|
|
}
|
|
|
|
CANSystemResourceManager::~CANSystemResourceManager() {
|
|
// 释放信号量
|
|
if (g_can_rx0_semaphore != NULL) {
|
|
osSemaphoreDelete(g_can_rx0_semaphore);
|
|
}
|
|
|
|
// 释放消息队列
|
|
if (g_can_rx0_queue != NULL) {
|
|
osMessageQueueDelete(g_can_rx0_queue);
|
|
}
|
|
|
|
// 释放对象池
|
|
if (can_message_pool != NULL) {
|
|
osMemoryPoolDelete(can_message_pool);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief CAN RX0 中断服务函数
|
|
* @note 处理CAN FIFO0的接收中断
|
|
*/
|
|
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
|
|
if (hcan->Instance == CAN1) {
|
|
CAN_RxHeaderTypeDef rx_msg_header;
|
|
|
|
if (HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO0) == 0) /* 没有接收到数据 */
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_msg_header, g_can_recv_msg.data) != HAL_OK) /* 读取数据 */
|
|
{
|
|
return;
|
|
}
|
|
#if 0
|
|
if (rx_msg_header.StdId != (CAN_BASE_FRAME_ID + CAN_CONFIG->getCanFrameId()) ||
|
|
rx_msg_header.IDE != CAN_ID_STD || rx_msg_header.RTR != CAN_RTR_DATA) /* 接收到的ID不对 / 不是标准帧 / 不是数据帧 */
|
|
{
|
|
return;
|
|
}
|
|
#else
|
|
if ((rx_msg_header.StdId != (CAN_BASE_FRAME_ID + CAN_CONFIG->getCanFrameId()) &&
|
|
rx_msg_header.StdId != (CAN_X_MOTOR_FRAME_ID + CAN_CONFIG->getCanFrameId()) &&
|
|
rx_msg_header.StdId != (CAN_Y_MOTOR_FRAME_ID + CAN_CONFIG->getCanFrameId())&&
|
|
rx_msg_header.StdId != (CAN_Z_MOTOR_FRAME_ID + CAN_CONFIG->getCanFrameId()))||
|
|
rx_msg_header.IDE != CAN_ID_STD || rx_msg_header.RTR != CAN_RTR_DATA) /* 接收到的ID不对 / 不是标准帧 / 不是数据帧 */
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
g_can_recv_msg.id = rx_msg_header.StdId;
|
|
g_can_recv_msg.length = rx_msg_header.DLC;
|
|
|
|
osSemaphoreRelease(g_can_rx0_semaphore);
|
|
}
|
|
}
|
|
|
|
CanController::CanController()
|
|
: tx_queue(NULL),
|
|
tx_task_handle(NULL) {
|
|
}
|
|
|
|
CanController::~CanController() {
|
|
stop();
|
|
}
|
|
|
|
bool CanController::start(CAN_HandleTypeDef* hcan) {
|
|
this->hcan = hcan;
|
|
// 启动CAN外围设备
|
|
CAN_FilterTypeDef sFilterConfig;
|
|
|
|
/* 配置CAN过滤器 */
|
|
sFilterConfig.FilterBank = 0; /* 过滤器0 */
|
|
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
|
|
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
|
|
sFilterConfig.FilterIdHigh = 0x0000; /* 32位ID */
|
|
sFilterConfig.FilterIdLow = 0x0000;
|
|
sFilterConfig.FilterMaskIdHigh = 0x0000; /* 32位MASK */
|
|
sFilterConfig.FilterMaskIdLow = 0x0000;
|
|
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; /* 过滤器0关联到FIFO0 */
|
|
sFilterConfig.FilterActivation = CAN_FILTER_ENABLE; /* 激活滤波器0 */
|
|
sFilterConfig.SlaveStartFilterBank = 14;
|
|
|
|
/* 过滤器配置 */
|
|
if (HAL_CAN_ConfigFilter(hcan, &sFilterConfig) != HAL_OK) {
|
|
Error_Handler();
|
|
}
|
|
|
|
if (HAL_CAN_Start(hcan) != HAL_OK) {
|
|
Error_Handler();
|
|
}
|
|
if (HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) {
|
|
Error_Handler();
|
|
}
|
|
mutex_tx_queue_ = osMutexNew(NULL);
|
|
|
|
// 创建发送队列
|
|
osMessageQueueAttr_t tx_queue_attr = {0};
|
|
tx_queue_attr.name = "tx_queue";
|
|
tx_queue = osMessageQueueNew(20, sizeof(CanMessage*), &tx_queue_attr);
|
|
if (tx_queue == NULL) {
|
|
return false;
|
|
}
|
|
|
|
// 创建发送任务
|
|
osThreadAttr_t tx_task_attr = {0};
|
|
tx_task_attr.name = "CanTxTask";
|
|
tx_task_attr.stack_size = 256 * 8;
|
|
tx_task_attr.priority = osPriorityNormal;
|
|
tx_task_handle = osThreadNew(canTxTask, this, &tx_task_attr);
|
|
if (tx_task_handle == NULL) {
|
|
return false;
|
|
}
|
|
|
|
// 创建协议解析任务
|
|
osThreadAttr_t parser_task_attr = {0};
|
|
parser_task_attr.name = "CanParserTask";
|
|
parser_task_attr.stack_size = 256 * 8;
|
|
parser_task_attr.priority = osPriorityNormal;
|
|
parser_task_handle = osThreadNew(canParserTask, this, &parser_task_attr);
|
|
if (parser_task_handle == NULL) {
|
|
osThreadTerminate(tx_task_handle);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CanController::stop() {
|
|
if (tx_task_handle != NULL) {
|
|
osThreadTerminate(tx_task_handle);
|
|
}
|
|
if (parser_task_handle != NULL) {
|
|
osThreadTerminate(parser_task_handle);
|
|
}
|
|
if (tx_queue != NULL) {
|
|
osMessageQueueDelete(tx_queue);
|
|
}
|
|
}
|
|
|
|
bool CanController::sendMessage(const CanMessage& msg) {
|
|
CanMessage* msgPtr = (CanMessage*)osMemoryPoolAlloc(can_message_pool, osWaitForever);
|
|
if (msgPtr == NULL) {
|
|
return false;
|
|
}
|
|
msg.cloneTo(msgPtr);
|
|
osMutexAcquire(mutex_tx_queue_, osWaitForever);
|
|
osStatus_t status = osMessageQueuePut(tx_queue, &msgPtr, 0U, 0U);
|
|
osMutexRelease(mutex_tx_queue_);
|
|
if (status != osOK) {
|
|
osMemoryPoolFree(can_message_pool, msgPtr);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CanController::canTxTask(void *argument) {
|
|
CanController* controller = static_cast<CanController*>(argument);
|
|
CanMessage *msgPtr = NULL;
|
|
CAN_TxHeaderTypeDef can_msg_header;
|
|
|
|
while (1) {
|
|
osStatus_t status = osMessageQueueGet(controller->tx_queue, &msgPtr, NULL, osWaitForever);
|
|
if (status == osOK) {
|
|
if(msgPtr == NULL)
|
|
{
|
|
return;
|
|
}
|
|
uint16_t t = 0;
|
|
uint32_t TxMailbox = CAN_TX_MAILBOX0;
|
|
|
|
can_msg_header.StdId = msgPtr->id;
|
|
can_msg_header.ExtId = msgPtr->id;
|
|
can_msg_header.IDE = CAN_ID_STD; // 标准帧
|
|
can_msg_header.RTR = CAN_RTR_DATA; // 数据帧
|
|
can_msg_header.DLC = msgPtr->length;
|
|
|
|
if (HAL_CAN_AddTxMessage(controller->hcan, &can_msg_header, msgPtr->data, &TxMailbox) != HAL_OK) /* 发送消息 */
|
|
{
|
|
osMemoryPoolFree(can_message_pool, msgPtr);
|
|
continue;
|
|
}
|
|
|
|
while (HAL_CAN_GetTxMailboxesFreeLevel(controller->hcan) != 3) /* 等待发送完成,所有邮箱为空 */
|
|
{
|
|
t++;
|
|
if (t > 0xFFF) {
|
|
HAL_CAN_AbortTxRequest(controller->hcan, TxMailbox); /* 超时,直接中止邮箱的发送请求 */
|
|
break;
|
|
}
|
|
}
|
|
osMemoryPoolFree(can_message_pool, msgPtr);
|
|
osDelay(2);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CanController::canParserTask(void *argument) {
|
|
#if 1
|
|
CanController* controller = static_cast<CanController*>(argument);
|
|
CanMessage *msgPtr = NULL;
|
|
while (1) {
|
|
osStatus_t status = osMessageQueueGet(g_can_rx0_queue, &msgPtr, NULL, osWaitForever);
|
|
if (status == osOK) {
|
|
if(msgPtr != NULL) {
|
|
controller->parser.parseMessage(msgPtr);
|
|
osMemoryPoolFree(can_message_pool, msgPtr);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|