mbed library sources, include can_api for nucleo-f091rc
Dependents: CanNucleoF0_example
Fork of mbed-src by
Revision 645:13c87cbecd54, committed 2016-01-07
- Comitter:
- ptpaterson
- Date:
- Thu Jan 07 05:49:05 2016 +0000
- Parent:
- 644:612d6aa9e717
- Commit message:
- corrected freeze on CAN_RECEIVE_IT
Changed in this revision
targets/hal/TARGET_STM/TARGET_STM32F0/can_api.cpp | Show annotated file Show diff for this revision Revisions of this file |
diff -r 612d6aa9e717 -r 13c87cbecd54 targets/hal/TARGET_STM/TARGET_STM32F0/can_api.cpp --- a/targets/hal/TARGET_STM/TARGET_STM32F0/can_api.cpp Mon Jan 04 06:10:26 2016 +0000 +++ b/targets/hal/TARGET_STM/TARGET_STM32F0/can_api.cpp Thu Jan 07 05:49:05 2016 +0000 @@ -95,64 +95,53 @@ * it freezes upon receiving a message (write is fine!) supports * my guess. */ -#define USE_RECEIVE_IT 0 + +/* holder for objects that need to be global */ +CAN_HandleTypeDef hcan; static PinName pinRd; static PinName pinTd; /** - * @brief - * @note - * @param - * @retval - */ -void -can_init (can_t *obj, - PinName rd, - PinName td) -{ + * @note + * @param + * @retval none + */ +void can_init (can_t *obj, PinName rd, PinName td) +{ // DEBUG printf("api: can_init\r\n"); - - /* file scope so that they can be referenced in the MSP functions */ + + /* set global pin values for MSP functions */ pinRd = rd; pinTd = td; - /* only one CAN controller for STM32F0, otherwise need to figure it out here */ -#if USE_RECEIVE_IT - single_can_controller = obj; /* this is so we can cheat and call globally*/ -#endif - obj->index = 0; + /* Set the peripheral pointer */ + hcan.Instance = ((CAN_TypeDef*)CAN_BASE); - /* initialize the static data */ - static CAN_HandleTypeDef hcan; - obj->hcan = &hcan; - obj->hcan->Instance = ((CAN_TypeDef *) CAN_BASE); - + /* initialize the mail boxes */ static CanTxMsgTypeDef txMessage; static CanRxMsgTypeDef rxMessage; - obj->hcan->pTxMsg = &txMessage; - obj->hcan->pRxMsg = &rxMessage; + hcan.pTxMsg = &txMessage; + hcan.pRxMsg = &rxMessage; - /* set operation mode */ - obj->hcan->Init.TTCM = DISABLE; - obj->hcan->Init.ABOM = ENABLE; - obj->hcan->Init.AWUM = DISABLE; - obj->hcan->Init.NART = DISABLE; - obj->hcan->Init.RFLM = DISABLE; - obj->hcan->Init.TXFP = DISABLE; - obj->hcan->Init.Mode = CAN_MODE_NORMAL; + /* Initialize the CAN peripheral */ + hcan.Init.TTCM = DISABLE; + hcan.Init.ABOM = ENABLE; + hcan.Init.AWUM = DISABLE; + hcan.Init.NART = DISABLE; + hcan.Init.RFLM = DISABLE; + hcan.Init.TXFP = DISABLE; + hcan.Init.Mode = CAN_MODE_NORMAL; - /* set th default frequency - * 125kbps bit rate (default) - * APB1 peripheral clock = 36000000Hz - */ - obj->hcan->Init.Prescaler = 18; // number of time quanta = 36000000/18/125000 = 16 - obj->hcan->Init.SJW = CAN_SJW_1TQ; - obj->hcan->Init.BS1 = CAN_BS1_11TQ; // sample point at (1 + 11) / 16 * 100 = 75% - obj->hcan->Init.BS2 = CAN_BS2_4TQ; + // 125kbps bit rate (default) + // APB1 peripheral clock = 48000000Hz + hcan.Init.Prescaler = 24; // number of time quanta = 48000000/24/125000 = 16 + hcan.Init.SJW = CAN_SJW_1TQ; + hcan.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% + hcan.Init.BS2 = CAN_BS2_4TQ; - int status = HAL_CAN_Init (obj->hcan); + int status = HAL_CAN_Init (&hcan); if (status != HAL_OK) { printf("api: can_init: HAL_CAN_INIT issue\r\n"); } @@ -172,7 +161,7 @@ void can_free (can_t *obj) { - HAL_CAN_DeInit (obj->hcan); + HAL_CAN_DeInit (&hcan); } /** @@ -181,55 +170,54 @@ * @param * @retval */ -int -can_frequency(can_t *obj, - int hz) +int can_frequency(can_t *obj, int hz) { HAL_NVIC_DisableIRQ(CEC_CAN_IRQn); - // APB1 peripheral clock = 36000000Hz - + // APB1 peripheral clock = 48000000Hz switch(hz) { case 1000000: // 1000kbps bit rate - obj->hcan->Init.Prescaler = 3; // number of time quanta = 36000000/3/1000000 = 12 - obj->hcan->Init.SJW = CAN_SJW_1TQ; - obj->hcan->Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% - obj->hcan->Init.BS2 = CAN_BS2_3TQ; + hcan.Init.Prescaler = 4; // number of time quanta = 48000000/4/1000000 = 12 + hcan.Init.SJW = CAN_SJW_1TQ; + hcan.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% + hcan.Init.BS2 = CAN_BS2_3TQ; break; case 500000: // 500kbps bit rate - obj->hcan->Init.Prescaler = 6; // number of time quanta = 36000000/6/500000 = 12 - obj->hcan->Init.SJW = CAN_SJW_1TQ; - obj->hcan->Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% - obj->hcan->Init.BS2 = CAN_BS2_3TQ; + hcan.Init.Prescaler = 8; // number of time quanta = 48000000/8/500000 = 12 + hcan.Init.SJW = CAN_SJW_1TQ; + hcan.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75% + hcan.Init.BS2 = CAN_BS2_3TQ; break; case 250000: // 250kbps - obj->hcan->Init.Prescaler = 9; // number of time quanta = 36000000/9/250000 = 16 - obj->hcan->Init.SJW = CAN_SJW_1TQ; - obj->hcan->Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% - obj->hcan->Init.BS2 = CAN_BS2_4TQ; + hcan.Init.Prescaler = 12; // number of time quanta = 48000000/12/250000 = 16 + hcan.Init.SJW = CAN_SJW_1TQ; + hcan.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% + hcan.Init.BS2 = CAN_BS2_4TQ; break; case 125000: // 125kbps - obj->hcan->Init.Prescaler = 18; // number of time quanta = 36000000/18/125000 = 16 - obj->hcan->Init.SJW = CAN_SJW_1TQ; - obj->hcan->Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% - obj->hcan->Init.BS2 = CAN_BS2_4TQ; + hcan.Init.Prescaler = 24; // number of time quanta = 48000000/24/125000 = 16 + hcan.Init.SJW = CAN_SJW_1TQ; + hcan.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% + hcan.Init.BS2 = CAN_BS2_4TQ; break; default: // 125kbps (default) - obj->hcan->Init.Prescaler = 18; // number of time quanta = 36000000/18/125000 = 16 - obj->hcan->Init.SJW = CAN_SJW_1TQ; - obj->hcan->Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% - obj->hcan->Init.BS2 = CAN_BS2_4TQ; + hcan.Init.Prescaler = 24; // number of time quanta = 48000000/24/125000 = 16 + hcan.Init.SJW = CAN_SJW_1TQ; + hcan.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75% + hcan.Init.BS2 = CAN_BS2_4TQ; + break; } - HAL_CAN_Init(obj->hcan); + + HAL_CAN_Init(&hcan); /* HAL_CAN_INIT will call HAL_CAN_MspInit, which will init the interupts */ @@ -241,93 +229,83 @@ * and used later in HAL_CAN_RxCpltCallback() */ -#if USE_RECEIVE_IT - - #define CAN_MESSAGE_QUEUE_SIZE 10 - - /** - * @brief Holder for obj* when not passed to function - * @note need this to cheat for now while we don't have a way to implement - * multiple CAN controllers - */ - static can_t *single_can_controller; - - /** - * @brief Queue to hold several incomming messages while we wait for the user - * to call for them. - * @note This is only necessary now, because the STM32 HAL handles the can - * receive FIFO by writing to the CAN_HandleTypeDef and popping from the built - * in queue. - */ - typedef struct { - int next; - unsigned int contain_mask; - CanRxMsgTypeDef queue[CAN_MESSAGE_QUEUE_SIZE]; - } can_message_queue; - - static can_message_queue message_queues[CAN_NUM]; - - /** - * @brief Adds one message to the queue - * @note sends indication of overflow if it happens but overwites anyway - */ - static int message_enqueue(can_t *obj, - CanRxMsgTypeDef *msg) - { - int result = 1; - - int next = message_queues[obj->index].next; - if (++next >= CAN_MESSAGE_QUEUE_SIZE) - next = 0; - - if (message_queues[obj->index].contain_mask & (1 << next)) - result = 0; /* overflow */ - - message_queues[obj->index].queue[next] = *msg; - message_queues[obj->index].next = next; - message_queues[obj->index].contain_mask |= next; - - return result; - } - - /** - * @brief Pops one message from the queue - * @note sends indication of overflow if it happens but overwites anyway - */ - static int message_dequeue(can_t *obj, - CanRxMsgTypeDef *msg) - { - int result = 1; - - int next = message_queues[obj->index].next; - - if (message_queues[obj->index].contain_mask & (1 << next)) { - - *msg = message_queues[obj->index].queue[next]; - message_queues[obj->index].contain_mask &= ~next; - - if (--next < 0) - next = CAN_MESSAGE_QUEUE_SIZE - 1; - message_queues[obj->index].next = next; - - } else { - result = 0; /* no current message */ - } - - return result; - } - - - /** becomes a pointer to the member function Can::_irq_handler */ - static can_irq_handler irq_handler; - - /** id is really just a pointer to the Can object - * useful for uC's that have multiple CAN devices - */ - static uint32_t can_irq_ids[CAN_NUM] = {0}; +#define CAN_MESSAGE_QUEUE_SIZE 10 -#endif /* USE_RECEIVE_IT */ +/** + * @brief Queue to hold several incomming messages while we wait for the user + * to call for them. + * @note This is only necessary now, because the STM32 HAL handles the can + * receive FIFO by writing to the CAN_HandleTypeDef and popping from the built + * in queue. + */ +typedef struct { + int next; + unsigned int contain_mask; + CanRxMsgTypeDef queue[CAN_MESSAGE_QUEUE_SIZE]; +} can_message_queue; + +static can_message_queue message_queues[CAN_NUM]; + +/** + * @brief Adds one message to the queue + * @note sends indication of overflow if it happens but overwites anyway + */ +static int message_enqueue(can_t *obj, + CanRxMsgTypeDef *msg) +{ + int result = 1; + + int next = message_queues[obj->index].next; + if (++next >= CAN_MESSAGE_QUEUE_SIZE) + next = 0; + + if (message_queues[obj->index].contain_mask & (1 << next)) + result = 0; /* overflow */ + + message_queues[obj->index].queue[next] = *msg; + message_queues[obj->index].next = next; + message_queues[obj->index].contain_mask |= next; + + return result; +} + +/** + * @brief Pops one message from the queue + * @note sends indication of overflow if it happens but overwites anyway + */ +static int message_dequeue(can_t *obj, + CanRxMsgTypeDef *msg) +{ + int result = 1; + + int next = message_queues[obj->index].next; + + if (message_queues[obj->index].contain_mask & (1 << next)) { + + *msg = message_queues[obj->index].queue[next]; + message_queues[obj->index].contain_mask &= ~next; + + if (--next < 0) + next = CAN_MESSAGE_QUEUE_SIZE - 1; + message_queues[obj->index].next = next; + + } else { + result = 0; /* no current message */ + } + + return result; +} + +/** becomes a pointer to the member function Can::_irq_handler */ +static can_irq_handler irq_handler; + +/** id is really just a pointer to the Can object + * useful for uC's that have multiple CAN devices + */ +static uint32_t can_irq_ids[CAN_NUM] = {0}; + + /** * @brief @@ -340,20 +318,18 @@ can_irq_handler handler, uint32_t id) { - #if USE_RECEIVE_IT - // DEBUG - printf("api: can_irq_init\r\n"); - - irq_handler = handler; - can_irq_ids[obj->index] = id; - - message_queues[obj->index].contain_mask = 0; - message_queues[obj->index].next = CAN_MESSAGE_QUEUE_SIZE - 1; - - if (HAL_CAN_Receive_IT (obj->hcan, CAN_FIFO0) != HAL_OK) { - printf("api: can_irq_init: receive failed\r\n"); - } - #endif /* USE_RECEIVE_IT */ + // DEBUG + printf("api: can_irq_init\r\n"); + + irq_handler = handler; + can_irq_ids[obj->index] = id; + + message_queues[obj->index].contain_mask = 0; + message_queues[obj->index].next = CAN_MESSAGE_QUEUE_SIZE - 1; + + if (HAL_CAN_Receive_IT (&hcan, CAN_FIFO0) != HAL_OK) { + printf("api: can_irq_init: receive failed\r\n"); + } } @@ -397,23 +373,23 @@ { // DEBUG printf("api: can_write\r\n"); - + if (msg.format == CANStandard) { - obj->hcan->pTxMsg->StdId = msg.id; - obj->hcan->pTxMsg->ExtId = 0x00; + hcan.pTxMsg->StdId = msg.id; + hcan.pTxMsg->ExtId = 0x00; } else { - obj->hcan->pTxMsg->StdId = 0x00; - obj->hcan->pTxMsg->ExtId = msg.id; + hcan.pTxMsg->StdId = 0x00; + hcan.pTxMsg->ExtId = msg.id; } - obj->hcan->pTxMsg->RTR = msg.type == CANData ? CAN_RTR_DATA : CAN_RTR_REMOTE; - obj->hcan->pTxMsg->IDE = msg.format == CANStandard ? CAN_ID_STD : CAN_ID_EXT; - obj->hcan->pTxMsg->DLC = msg.len; + hcan.pTxMsg->RTR = msg.type == CANData ? CAN_RTR_DATA : CAN_RTR_REMOTE; + hcan.pTxMsg->IDE = msg.format == CANStandard ? CAN_ID_STD : CAN_ID_EXT; + hcan.pTxMsg->DLC = msg.len; - memcpy(obj->hcan->pTxMsg->Data, &(msg.data), msg.len); + memcpy(hcan.pTxMsg->Data, &(msg.data), msg.len); int result = 1; - if (HAL_CAN_Transmit(obj->hcan, 10) != HAL_OK) { + if (HAL_CAN_Transmit(&hcan, 5) != HAL_OK) { result = 0; } @@ -432,47 +408,22 @@ CAN_Message *msg, int handle) { + int result = 0; - - #if USE_RECEIVE_IT - CanRxMsgTypeDef popMessage; - if (message_dequeue (obj, &popMessage)) { - - msg->id = popMessage.IDE == CAN_ID_STD ? popMessage.StdId : popMessage.ExtId; - msg->type = popMessage.RTR == CAN_RTR_DATA ? CANData : CANRemote; - msg->format = popMessage.IDE == CAN_ID_STD ? CANStandard : CANExtended; - msg->len = popMessage.DLC; - - memcpy(msg->data, &(popMessage.Data), msg->len); - - result = msg->len; - } - #else - CanRxMsgTypeDef *popMessage = obj->hcan->pRxMsg; - HAL_StatusTypeDef status = HAL_CAN_Receive (obj->hcan, CAN_FIFO0, 10); - if (status == HAL_OK) { - printf("api: can_read: HAL_OK\r\n"); - - msg->id = popMessage->IDE == CAN_ID_STD ? popMessage->StdId : popMessage->ExtId; - msg->type = popMessage->RTR == CAN_RTR_DATA ? CANData : CANRemote; - msg->format = popMessage->IDE == CAN_ID_STD ? CANStandard : CANExtended; - msg->len = popMessage->DLC; - - memcpy(msg->data, &(popMessage->Data), msg->len); - - result = msg->len; - - - } else if (status == HAL_ERROR) { - printf("api: can_read: HAL_ERROR\r\n"); - } else if (status == HAL_BUSY) { - printf("api: can_read: HAL_BUSY\r\n"); - } else if (status == HAL_TIMEOUT) { - } else { - printf("api: can_read: UNKNOWN STATUS!!!!!!!\r\n"); - } - #endif /* USE_RECEIVE_IT */ - + + CanRxMsgTypeDef popMessage; + if (message_dequeue (obj, &popMessage)) { + + msg->id = popMessage.IDE == CAN_ID_STD ? popMessage.StdId : popMessage.ExtId; + msg->type = popMessage.RTR == CAN_RTR_DATA ? CANData : CANRemote; + msg->format = popMessage.IDE == CAN_ID_STD ? CANStandard : CANExtended; + msg->len = popMessage.DLC; + + memcpy(msg->data, &(popMessage.Data), msg->len); + + result = msg->len; + } + return result; } @@ -494,28 +445,28 @@ break; case MODE_NORMAL: - obj->hcan->Init.Mode = CAN_MODE_NORMAL; + hcan.Init.Mode = CAN_MODE_NORMAL; break; case MODE_SILENT: - obj->hcan->Init.Mode = CAN_MODE_SILENT; + hcan.Init.Mode = CAN_MODE_SILENT; break; case MODE_TEST_GLOBAL: - obj->hcan->Init.Mode = CAN_MODE_LOOPBACK; + hcan.Init.Mode = CAN_MODE_LOOPBACK; break; case MODE_TEST_LOCAL: - obj->hcan->Init.Mode = CAN_MODE_LOOPBACK; + hcan.Init.Mode = CAN_MODE_LOOPBACK; break; case MODE_TEST_SILENT: - obj->hcan->Init.Mode = CAN_MODE_SILENT_LOOPBACK; + hcan.Init.Mode = CAN_MODE_SILENT_LOOPBACK; break; } if (success != HAL_ERROR) { - success = HAL_CAN_Init(obj->hcan); + success = HAL_CAN_Init(&hcan); } return success; @@ -547,7 +498,7 @@ sFilterConfig.FilterActivation = ENABLE; sFilterConfig.BankNumber = 0; // Selects the start bank filter - return HAL_CAN_ConfigFilter(obj->hcan, &sFilterConfig); + return HAL_CAN_ConfigFilter(&hcan, &sFilterConfig); } /** @@ -559,7 +510,7 @@ void can_reset (can_t *obj) { - __HAL_CAN_RESET_HANDLE_STATE(obj->hcan); + __HAL_CAN_RESET_HANDLE_STATE(&hcan); } /** @@ -571,7 +522,7 @@ unsigned char can_rderror (can_t *obj) { - return HAL_CAN_GetError(obj->hcan); + return HAL_CAN_GetError(&hcan); } /** @@ -583,7 +534,7 @@ unsigned char can_tderror (can_t *obj) { - return HAL_CAN_GetError(obj->hcan); + return HAL_CAN_GetError(&hcan); } /** @@ -603,70 +554,66 @@ * HAL_MSP and other functions *============================================================================= */ - + /** * @brief CAN MSP Initialization * @param hcan: CAN handle pointer * @retval None */ -void -HAL_CAN_MspInit(CAN_HandleTypeDef* hcan) +void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan) { - // DEBUG - printf("Msp: HAL_CAN_MspInit\r\n"); - - /* derived from STM32CubeMX */ - GPIO_InitTypeDef GPIO_InitStruct; - if (hcan->Instance == ((CAN_TypeDef *) CAN_BASE)) { - if ((pinRd == PA_11) && (pinTd == PA_12)) { - - /* Peripheral clock enable */ - __CAN_CLK_ENABLE(); + + if((pinRd == PA_11) && (pinTd == PA_12)) { + + /* CAN1 Periph clock enable */ + __CAN_CLK_ENABLE(); - /* Enable GPIO clock */ - __GPIOA_CLK_ENABLE(); + /* Enable GPIO clock */ + __GPIOA_CLK_ENABLE(); + + /* CAN1 RX GPIO pin configuration */ + GPIO_InitStruct.Pin = GPIO_PIN_11; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF4_CAN; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - /**CAN GPIO Configuration - PA11 ------> CAN_RX - PA12 ------> CAN_TX - */ - GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF4_CAN; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - } else if ((pinRd == PB_8) && (pinTd == PB_9)) { - /* Peripheral clock enable */ - __CAN_CLK_ENABLE(); + /* CAN1 TX GPIO pin configuration */ + GPIO_InitStruct.Pin = GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF4_CAN; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + } else if((pinRd == PB_8) && (pinTd == PB_9)) { + /* CAN1 Periph clock enable */ + __CAN_CLK_ENABLE(); - /* Enable GPIO clock */ - __GPIOB_CLK_ENABLE(); + /* Enable GPIO clock */ + __GPIOB_CLK_ENABLE(); - /**CAN GPIO Configuration - PB8 ------> CAN_RX - PB9 ------> CAN_TX - */ - GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF4_CAN; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - } else { - printf("bad pins defined in CAN class\r\n"); - } + /* CAN1 RX GPIO pin configuration */ + GPIO_InitStruct.Pin = GPIO_PIN_8; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF4_CAN; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - #if USE_RECEIVE_IT - /* Peripheral interrupt init*/ - HAL_NVIC_SetPriority(CEC_CAN_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(CEC_CAN_IRQn); - #endif /* USE_RECEIVE_IT */ - } else { - printf("CAN_HandleTypeDef instance bad\r\n"); - } - + /* CAN1 TX GPIO pin configuration */ + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF4_CAN; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + } else + return; + /* NVIC configuration for CAN1 Reception complete interrupt */ + HAL_NVIC_SetPriority(CEC_CAN_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(CEC_CAN_IRQn); } /** @@ -677,90 +624,100 @@ * @param hcan: CAN handle pointer * @retval None */ -void -HAL_CAN_MspDeInit (CAN_HandleTypeDef* hcan) +void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan) { - // DEBUG - printf("Msp: HAL_CAN_MspDeInit\r\n"); - - /* derived from STM32CubeMX */ + + /* Reset peripherals */ - if (hcan->Instance == ((CAN_TypeDef *) CAN_BASE)) { - /* Peripheral clock disable */ - __CAN_CLK_DISABLE(); + __CAN_FORCE_RESET(); + __CAN_RELEASE_RESET(); - /* Disable pins*/ - if ((pinRd == PA_11) && (pinTd == PA_12)) { - /**CAN GPIO Configuration - PA11 ------> CAN_RX - PA12 ------> CAN_TX - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); - } else if ((pinRd == PB_8) && (pinTd == PB_9)) { - /**CAN GPIO Configuration - PB8 ------> CAN_RX - PB9 ------> CAN_TX - */ - HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9); - } else {} + /* Disable peripherals and GPIO Clocks */ + if((pinRd == PA_11) && (pinTd == PA_12)) { + /* De-initialize the CAN1 RX GPIO pin */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11); + + /* De-initialize the CAN1 TX GPIO pin */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_12); + } else { + + /* De-initialize the CAN1 RX GPIO pin */ + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8); + + /* De-initialize the CAN1 TX GPIO pin */ + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9); } - #if USE_RECEIVE_IT - /* Disable the NVIC for CAN reception */ - HAL_NVIC_DisableIRQ(CEC_CAN_IRQn); - #endif /* USE_RECEIVE_IT */ + + /* Disable the NVIC for CAN reception */ + HAL_NVIC_DisableIRQ(CEC_CAN_IRQn); +} + +/** +* @brief Handles CAN RX0 interrupt request. +* @param None +* @note STM32F0 uses different interrupts than F4 +* @retval None +*/ +void CEC_CAN_IRQHandler(void) +{ + HAL_CAN_IRQHandler(&hcan); } -#if USE_RECEIVE_IT - /** - * @brief Reception complete callback in non blocking mode - * @param obj->hcan: pointer to a CAN_HandleTypeDef structure that contains - * the configuration information for the specified CAN. - * @retval None - */ - void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan) - { - /* Add message we jsut received to the can_message_queue */ - /* cheats and uses global pointer to the only can_t used for STM32 F0 */ - message_enqueue(single_can_controller, hcan->pRxMsg); - - /* Call user callback */ - irq_handler (can_irq_ids[0], IRQ_RX); + +/** + * @brief Reception complete callback in non blocking mode + * @param hcan: pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan) +{ + // if(HAL_CAN_Receive_IT(hcan, CAN_FIFO0) == HAL_OK) { + // if(rxCompleteCallback != NULL) + // rxCompleteCallback(); + // } + // else { + // error_handler(error); + // } + + // BUG: CAN race condition if HAL_CAN_Receive_IT() is used. + // See https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FSTM32Java%2FBUG%20CAN%20race%20condition%20if%20HAL%5FCAN%5FReceive%5FIT%20is%20used + // + // Fixed by Mark Burton: + // ideally, we should be able to call HAL_CAN_Receive_IT() here to set up for another + // receive but the API is flawed because that function will fail if HAL_CAN_Transmit() + // had already locked the handle when the receive interrupt occurred - so we do what + // HAL_CAN_Receive_IT() would do + - /* - * BUG: CAN race condition if HAL_CAN_Receive_IT() is used. - * See https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FSTM32Java%2FBUG%20CAN%20race%20condition%20if%20HAL%5FCAN%5FReceive%5FIT%20is%20used - * - * Fixed by Mark Burton: - * ideally, we should be able to call HAL_CAN_Receive_IT() here to set up for another - * receive but the API is flawed because that function will fail if HAL_CAN_Transmit() - * had already locked the handle when the receive interrupt occurred - so we do what - * HAL_CAN_Receive_IT() would do - */ - - /* perform HAL_CAN_Receive_IT() fix */ - if (hcan->State == HAL_CAN_STATE_BUSY_TX) { - hcan->State = HAL_CAN_STATE_BUSY_TX_RX; - } else { - hcan->State = HAL_CAN_STATE_BUSY_RX; - - /* Set CAN error code to none */ - hcan->ErrorCode = HAL_CAN_ERROR_NONE; - /* Enable Error warning Interrupt */ - __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG); - /* Enable Error passive Interrupt */ - __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EPV); - /* Enable Bus-off Interrupt */ - __HAL_CAN_ENABLE_IT(hcan, CAN_IT_BOF); - /* Enable Last error code Interrupt */ - __HAL_CAN_ENABLE_IT(hcan, CAN_IT_LEC); - /* Enable Error Interrupt */ - __HAL_CAN_ENABLE_IT(hcan, CAN_IT_ERR); - } - - // Enable FIFO 0 message pending Interrupt - __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FMP0); - + irq_handler (can_irq_ids[0], IRQ_RX); + + if (hcan->State == HAL_CAN_STATE_BUSY_TX) + hcan->State = HAL_CAN_STATE_BUSY_TX_RX; + else { + hcan->State = HAL_CAN_STATE_BUSY_RX; + + /* Set CAN error code to none */ + hcan->ErrorCode = HAL_CAN_ERROR_NONE; + + /* Enable Error warning Interrupt */ + __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG); + + /* Enable Error passive Interrupt */ + __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EPV); + + /* Enable Bus-off Interrupt */ + __HAL_CAN_ENABLE_IT(hcan, CAN_IT_BOF); + + /* Enable Last error code Interrupt */ + __HAL_CAN_ENABLE_IT(hcan, CAN_IT_LEC); + + /* Enable Error Interrupt */ + __HAL_CAN_ENABLE_IT(hcan, CAN_IT_ERR); } -#endif /* USE_RECEIVE_IT */ + + // Enable FIFO 0 message pending Interrupt + __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FMP0); +}