diff --git a/f1/can/include/can.h b/f1/can/include/can.h new file mode 100644 index 0000000000000000000000000000000000000000..3c1d1f589e3b588c609559a9fc3a1f385c2fc1a9 --- /dev/null +++ b/f1/can/include/can.h @@ -0,0 +1,104 @@ +#ifndef CAN_F1_H +#define CAN_F1_H + +#include "stm32f1xx_hal.h" +#include "comm.h" + +typedef struct +{ + unsigned char irq_priority; + unsigned char irq_subpriority; +}TCAN_IRQ_Priorities; + +typedef enum +{ + CAN_10KBPS, + CAN_20KBPS, + CAN_50KBPS, + CAN_83K3BPS, + CAN_100KBPS, + CAN_125KBPS, + CAN_250KBPS, + CAN_500KBPS, + CAN_1000KBPS +} CAN_SPEED; + +typedef enum +{ + VERSION_1, + VERSION_2, + VERSION_NULL +} DynamixelVersion; + +typedef struct TDynamixelMessage +{ + unsigned char received_bytes; +/** + * \brief + * + */ + unsigned char rx_buffer[MAX_DYN_SLAVE_RX_BUFFER_LEN]; +/** + * \brief + * + */ + unsigned char Len_L; +/** + * \brief + * + */ + unsigned char Len_H; +/** + * \brief + * + */ + unsigned int length; +/** + * \brief + * + */ + DynamixelVersion version; +/** + * \brief + * + */ + unsigned char packet_init; +/** + * \brief + * + */ + unsigned char packet_incomplete; +/** + * \brief + * + */ + unsigned char send_packet; +/** + * \brief + * + */ + unsigned char iterations; +/** + * \brief + * + */ +}TDynamixelMessage; + +/* public functions */ +void can_init(TComm *comm_dev,CAN_InitTypeDef *conf,TCAN_IRQ_Priorities *priorities); +void can_config(TComm *comm_dev,CAN_InitTypeDef *conf); +void can_set_priorities(TComm *comm_dev,TCAN_IRQ_Priorities *priorities); +void can_set_bitrate(TComm *comm_dev,CAN_SPEED bitrate); +void can_set_filter(TComm *comm_dev,CAN_FilterConfTypeDef *filter); +void can_set_can_id(TComm *comm_dev,unsigned char id); +/* IRQ functions */ +unsigned char can_send_irq(unsigned char first_byte); +unsigned char can_enable_tx_irq(void); +unsigned char can_receive_irq(void); +unsigned char can_cancel_receive_irq(void); +/* DMA functions */ +unsigned char can_send_dma(unsigned char *data,unsigned short int length); +unsigned char can_receive_dma(unsigned char *data,unsigned short int length); +unsigned char can_cancel_receive_dma(void); + +#endif diff --git a/f1/can/include/can_common.h b/f1/can/include/can_common.h new file mode 100644 index 0000000000000000000000000000000000000000..f7eabaff39d5986f886369ab1df4663a2b8ff2ad --- /dev/null +++ b/f1/can/include/can_common.h @@ -0,0 +1,22 @@ +#ifndef CAN_COMMON_F1_H +#define CAN_COMMON_F1_H + +typedef struct +{ + unsigned char irq_priority; + unsigned char irq_subpriority; +}TCAN_IRQ_Priorities; + +enum CAN_SPEED { //only applies when APB1 = 36Mhz + CAN_10KBPS, + CAN_20KBPS, + CAN_50KBPS, + CAN_83K3BPS, + CAN_100KBPS, + CAN_125KBPS, + CAN_250KBPS, + CAN_500KBPS, + CAN_1000KBPS +}; + +#endif diff --git a/f1/can/src/can.c b/f1/can/src/can.c new file mode 100644 index 0000000000000000000000000000000000000000..bc95bcb1affd6685e2bfdcc5212e49d8da8a549e --- /dev/null +++ b/f1/can/src/can.c @@ -0,0 +1,469 @@ +#include "can.h" + +#define CAN CAN1 +#define CAN_ENABLE_CLK __HAL_RCC_CAN1_CLK_ENABLE() +#define CAN_IRQnRX USB_LP_CAN1_RX0_IRQn +#define CAN_IRQnTX USB_HP_CAN1_TX_IRQn +#define CAN_IRQHandler USB_LP_CAN1_RX0CAN_IRQHandler + +#define CAN_TX_PIN GPIO_PIN_9 +#define CAN_TX_GPIO_PORT GPIOB +#define CAN_ENABLE_TX_GPIO_CLK __HAL_RCC_GPIOB_CLK_ENABLE() + +#define CAN_RX_PIN GPIO_PIN_8 +#define CAN_RX_GPIO_PORT GPIOB +#define CAN_ENABLE_RX_GPIO_CLK __HAL_RCC_GPIOB_CLK_ENABLE() + +// private variables +CAN_HandleTypeDef CANHandle; +CAN_FilterConfTypeDef CANFilterConfig; +CanTxMsgTypeDef CAN_txMessage; +CanRxMsgTypeDef CAN_rxMessage; + +TComm *can_comm_dev; +unsigned char can_dma_phase; +unsigned char *can_dma_phase_data; +unsigned short int can_dma_phase_length; +unsigned short int can_dma_phase_write_ptr; + +unsigned char can_missing_bytes_data[255]; +unsigned short int can_missing_bytes_length; +unsigned short int can_missing_bytes_write_ptr; + +unsigned short int can_send_lenght; +unsigned short int can_send_iterations; +unsigned char can_send_data[255]; + +TDynamixelMessage message; + +// 1 +void can_init(TComm *comm_dev,CAN_InitTypeDef *conf,TCAN_IRQ_Priorities *priorities) +{ + CANHandle.Instance = CAN1; + can_config(comm_dev,conf); + + GPIO_InitTypeDef GPIO_InitStructure; + + /* Enable GPIO clock */ + CAN_ENABLE_TX_GPIO_CLK; + CAN_ENABLE_RX_GPIO_CLK; + + CAN_ENABLE_CLK; + + /**CAN GPIO Configuration + PB8 ------> CAN_RX + PB9 ------> CAN_TX + */ + /* Configure CAN Tx and Rx as alternate function push-pull */ + GPIO_InitStructure.Pin = CAN_RX_PIN; + GPIO_InitStructure.Pull = GPIO_MODE_INPUT; + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + HAL_GPIO_Init(CAN_RX_GPIO_PORT, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = CAN_TX_PIN; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(CAN_TX_GPIO_PORT, &GPIO_InitStructure); + + __HAL_AFIO_REMAP_CAN1_2(); + + can_set_priorities(comm_dev,priorities); + + HAL_CAN_Init(&CANHandle); + + /* Initialize the comm structure */ + comm_dev->send_irq=can_send_irq; + comm_dev->enable_tx_irq=can_enable_tx_irq; + comm_dev->receive_irq=can_receive_irq; + comm_dev->cancel_receive_irq=can_cancel_receive_irq; + if(comm_dev->use_dma) + { + comm_dev->send_dma=can_send_dma; + comm_dev->receive_dma=can_receive_dma; + comm_dev->cancel_receive_dma=can_cancel_receive_dma; + } + comm_dev->irq_send_cb=0x00000000; + comm_dev->irq_receive_cb=0x00000000; + comm_dev->dma_send_cb=0x00000000; + comm_dev->dma_receive_cb=0x00000000; + + // /* initialize internal variables */ + can_comm_dev=comm_dev; + + can_dma_phase=0x00; + can_dma_phase_data=0x00; + can_dma_phase_length=0; + can_dma_phase_write_ptr=0; + can_missing_bytes_length = 0; + can_missing_bytes_write_ptr = 0; + can_send_lenght = 0; + can_send_iterations = 0; + + message.packet_init = 0x00; + message.packet_incomplete = 0x00; + message.send_packet = 0x00; + message.iterations = 0; + /////////////////////////////////////////////////////////////////////////// + CANFilterConfig.FilterNumber = 0; + CANFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; + CANFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; + CANFilterConfig.FilterIdHigh = 0x0000; + CANFilterConfig.FilterIdLow = 0x0000; + CANFilterConfig.FilterMaskIdHigh = 0x0000; + CANFilterConfig.FilterMaskIdLow = 0x0000; + CANFilterConfig.FilterFIFOAssignment = 0; + CANFilterConfig.FilterActivation = ENABLE; + CANFilterConfig.BankNumber = 0; + + HAL_CAN_ConfigFilter(&CANHandle, &CANFilterConfig); + + + CANHandle.pRxMsg = &CAN_rxMessage; + CANHandle.pTxMsg = &CAN_txMessage; + + CANHandle.pTxMsg->StdId = 0x00; + CANHandle.pTxMsg->ExtId = 0x01; + CANHandle.pTxMsg->RTR = CAN_RTR_DATA; + CANHandle.pTxMsg->IDE = CAN_ID_STD; + + //HAL_CAN_Receive_IT(&CANHandle,CAN_FIFO0); + +} + +void can_config(TComm *comm_dev,CAN_InitTypeDef *conf) +{ + CANHandle.Init.Prescaler = conf->Prescaler; + CANHandle.Init.Mode = conf->Mode; + CANHandle.Init.SJW = conf->SJW; + CANHandle.Init.BS1 = conf->BS1; + CANHandle.Init.BS2 = conf->BS2; + CANHandle.Init.TTCM = conf->TTCM; + CANHandle.Init.ABOM = conf->ABOM; + CANHandle.Init.AWUM = conf->AWUM; + CANHandle.Init.NART = conf->NART; + CANHandle.Init.RFLM = conf->RFLM; + CANHandle.Init.TXFP = conf->TXFP; +} + +void can_set_priorities(TComm *comm_dev,TCAN_IRQ_Priorities *priorities) +{ + HAL_NVIC_SetPriority(CAN_IRQnRX, priorities->irq_priority, priorities->irq_subpriority); + HAL_NVIC_EnableIRQ(CAN_IRQnRX); + HAL_NVIC_SetPriority(CAN_IRQnTX, priorities->irq_priority, priorities->irq_subpriority); + HAL_NVIC_EnableIRQ(CAN_IRQnTX); +} + +void can_set_bitrate(TComm *comm_dev,CAN_SPEED bitrate) +{ + switch (bitrate) { + case CAN_10KBPS: + CANHandle.Init.Prescaler = 225; + CANHandle.Init.BS1 = CAN_BS1_13TQ; + CANHandle.Init.BS2 = CAN_BS2_2TQ; + CANHandle.Init.SJW = CAN_SJW_1TQ; + break; + case CAN_20KBPS: + CANHandle.Init.Prescaler = 100; + CANHandle.Init.BS1 = CAN_BS1_15TQ; + CANHandle.Init.BS2 = CAN_BS2_2TQ; + CANHandle.Init.SJW = CAN_SJW_1TQ; + break; + case CAN_50KBPS: + CANHandle.Init.Prescaler = 45; + CANHandle.Init.BS1 = CAN_BS1_13TQ; + CANHandle.Init.BS2 = CAN_BS2_2TQ; + CANHandle.Init.SJW = CAN_SJW_1TQ; + break; + case CAN_83K3BPS: + CANHandle.Init.Prescaler = 27; + CANHandle.Init.BS1 = CAN_BS1_13TQ; + CANHandle.Init.BS2 = CAN_BS2_2TQ; + CANHandle.Init.SJW = CAN_SJW_1TQ; + break; + case CAN_100KBPS: + CANHandle.Init.Prescaler = 20; + CANHandle.Init.BS1 = CAN_BS1_15TQ; + CANHandle.Init.BS2 = CAN_BS2_2TQ; + CANHandle.Init.SJW = CAN_SJW_1TQ; + break; + case CAN_125KBPS: + CANHandle.Init.Prescaler = 18; + CANHandle.Init.BS1 = CAN_BS1_13TQ; + CANHandle.Init.BS2 = CAN_BS2_2TQ; + CANHandle.Init.SJW = CAN_SJW_1TQ; + break; + case CAN_250KBPS: + CANHandle.Init.Prescaler = 9; + CANHandle.Init.BS1 = CAN_BS1_13TQ; + CANHandle.Init.BS2 = CAN_BS2_2TQ; + CANHandle.Init.SJW = CAN_SJW_1TQ; + break; + case CAN_500KBPS: + CANHandle.Init.Prescaler = 4; + CANHandle.Init.BS1 = CAN_BS1_15TQ; + CANHandle.Init.BS2 = CAN_BS2_2TQ; + CANHandle.Init.SJW = CAN_SJW_1TQ; + break; + case CAN_1000KBPS: + CANHandle.Init.Prescaler = 2; + CANHandle.Init.BS1 = CAN_BS1_15TQ; + CANHandle.Init.BS2 = CAN_BS2_2TQ; + CANHandle.Init.SJW = CAN_SJW_1TQ; + break; + } +} + +void can_set_filter(TComm *comm_dev,CAN_FilterConfTypeDef *filter) +{ + HAL_CAN_ConfigFilter(&CANHandle, filter); + //HAL_CAN_Receive_IT(&CANHandle,CAN_FIFO0); +} + +void can_set_can_id(TComm *comm_dev,unsigned char id) +{ + CANHandle.pTxMsg->StdId = id; +} + +/** + * HAL_CAN_ErrorCallback + * Callback function for CAN errors. + * @param CANHandle Pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for a given CAN peripheral. + */ +void HAL_CAN_ErrorCallback(CAN_HandleTypeDef* CANHandle) +{ + //HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4,GPIO_PIN_SET); +} + + +void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* CANHandle) +{ + // HAL_CAN_StateTypeDef status = HAL_CAN_GetState(CANHandle); + // while(HAL_CAN_STATE_READY != status) + // { + // status = HAL_CAN_GetState(CANHandle); + // } + + if (can_send_lenght != 0) + { + if (can_send_lenght > 8) + { + for (uint8_t i=0;i<8;i++) + { + CANHandle->pTxMsg->Data[i] = can_send_data[i+(8*can_send_iterations)]; + } + can_send_lenght = can_send_lenght - 8; + can_send_iterations++; + HAL_CAN_Transmit_IT(CANHandle); + } + else + { + for (uint8_t i=0;i<can_send_lenght;i++) + { + CANHandle->pTxMsg->Data[i] = can_send_data[i+(8*can_send_iterations)]; + } + can_send_lenght = 0; + can_send_iterations = 0; + HAL_CAN_Transmit_IT(CANHandle); + uint8_t byte; + comm_do_dma_send(can_comm_dev); + comm_do_irq_send(can_comm_dev,&byte); + } + } + //__HAL_CAN_DISABLE_IT(CANHandle,CAN_IT_TME); + __HAL_CAN_CLEAR_FLAG(CANHandle,CAN_FLAG_RQCP0); + __HAL_CAN_CLEAR_FLAG(CANHandle,CAN_FLAG_TXOK0); +} + +void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CANHandle) +{ + if(can_missing_bytes_length == 0){ + for(uint8_t i=0;i<CAN_rxMessage.DLC;i++) + { + if(!can_dma_phase) + comm_do_irq_receive(can_comm_dev,CAN_rxMessage.Data[i]); + else + { + if(can_dma_phase_length<5){ + can_dma_phase_data[can_dma_phase_write_ptr]=CAN_rxMessage.Data[i]; + can_dma_phase_length--; + can_dma_phase_write_ptr++; + if(can_dma_phase_length==0){ + comm_do_dma_receive(can_comm_dev); + } + } + } + } + if(can_dma_phase_length>4){ + for(uint8_t i=0;i<CAN_rxMessage.DLC;i++) + can_missing_bytes_data[i] = CAN_rxMessage.Data[i]; + can_missing_bytes_length = can_dma_phase_length-4; + can_missing_bytes_write_ptr = 7; + } + } + else + { + if(can_missing_bytes_length<=8){ + for(uint8_t i=0;i<CAN_rxMessage.DLC;i++) + { + can_missing_bytes_write_ptr++; + can_missing_bytes_length--; + can_missing_bytes_data[can_missing_bytes_write_ptr] = CAN_rxMessage.Data[i]; + } + for(uint8_t i=0;i<=can_missing_bytes_write_ptr;i++) + { + if(!can_dma_phase) + comm_do_irq_receive(can_comm_dev,can_missing_bytes_data[i]); + else + { + can_dma_phase_data[can_dma_phase_write_ptr]=can_missing_bytes_data[i]; + can_dma_phase_length--; + can_dma_phase_write_ptr++; + if(can_dma_phase_length==0){ + comm_do_dma_receive(can_comm_dev); + can_missing_bytes_length = 0; + can_missing_bytes_write_ptr = 0; + } + } + } + } + else + { + for(uint8_t i=0;i<CAN_rxMessage.DLC;i++) + { + can_missing_bytes_write_ptr++; + can_missing_bytes_length--; + can_missing_bytes_data[can_missing_bytes_write_ptr] = CAN_rxMessage.Data[i]; + } + } + } +} + +// interrupt handlers +void USB_LP_CAN1_RX0_IRQHandler(void) +{ + /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 */ + + /* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */ + HAL_CAN_IRQHandler(&CANHandle); + /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 */ + + /* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */ +} + +void USB_HP_CAN1_TX_IRQHandler(void) +{ + /* USER CODE BEGIN USB_HP_CAN1_TX_IRQn 0 */ + + /* USER CODE END USB_HP_CAN1_TX_IRQn 0 */ + HAL_CAN_IRQHandler(&CANHandle); + /* USER CODE BEGIN USB_HP_CAN1_TX_IRQn 1 */ + + /* USER CODE END USB_HP_CAN1_TX_IRQn 1 */ +} + +unsigned char can_send_irq(unsigned char first_byte) +{ + return 0x00; +} + +unsigned char can_enable_tx_irq(void) +{ + return 0x00; +} + +unsigned char can_receive_irq(void) +{ + can_dma_phase=0x00; + can_dma_phase_write_ptr=0x00; + HAL_CAN_Receive_IT(&CANHandle,CAN_FIFO0); + return 0x00; +} + +unsigned char can_cancel_receive_irq(void) +{ + return 0x00; +} + +/* DMA functions */ +unsigned char can_send_dma(unsigned char *data,unsigned short int length) +{ + // if (length <= 8) + // { + // CANHandle.pTxMsg->DLC = length; + // for (uint8_t i=0;i<length;i++) + // { + // CANHandle.pTxMsg->Data[i] = data[i]; + // } + // HAL_CAN_Transmit_IT(&CANHandle); + // } + // else + // { + // unsigned char iterations = 0x00; + // while (length > 0) + // { + // if(length > 8) + // CANHandle.pTxMsg->DLC = 8; + // else + // CANHandle.pTxMsg->DLC = length; + // for (uint8_t i=0;i<CANHandle.pTxMsg->DLC;i++) + // { + // CANHandle.pTxMsg->Data[i] = data[i+iterations]; + // } + // HAL_CAN_Transmit_IT(&CANHandle); + // HAL_Delay(5); + // iterations = iterations + 8; + // length = length - CANHandle.pTxMsg->DLC; + // } + // } + + if(length > 8){ + CANHandle.pTxMsg->DLC = 8; + for (uint8_t i=0;i<length;i++) + { + can_send_data[i] = data[i]; + } + can_send_lenght = length - 8; + can_send_iterations = 1; + for (uint8_t i=0;i<8;i++) + { + CANHandle.pTxMsg->Data[i] = data[i]; + } + HAL_CAN_Transmit_IT(&CANHandle); + } + else{ + CANHandle.pTxMsg->DLC = length; + for (uint8_t i=0;i<length;i++) + { + CANHandle.pTxMsg->Data[i] = data[i]; + } + HAL_CAN_Transmit_IT(&CANHandle); + uint8_t byte; + comm_do_dma_send(can_comm_dev); + comm_do_irq_send(can_comm_dev,&byte); + } + //HAL_CAN_Transmit_IT(&CANHandle); + __HAL_CAN_CLEAR_FLAG(&CANHandle,CAN_FLAG_RQCP0); + __HAL_CAN_CLEAR_FLAG(&CANHandle,CAN_FLAG_TXOK0); + return 0x00; +} + +unsigned char can_receive_dma(unsigned char *data,unsigned short int length) +{ + can_dma_phase=0x01; + can_dma_phase_data=data; + can_dma_phase_length=length; + can_dma_phase_write_ptr=0; + + return 0x00; +} + +unsigned char can_cancel_receive_dma(void) +{ + can_dma_phase=0x00; + can_dma_phase_data=0x00; + can_dma_phase_length=0; + can_dma_phase_write_ptr=0; + + return 0x00; +}