void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan) { GPIO_InitTypeDef GPIO_InitStruct; if(hcan->Instance==CAN) { /* USER CODE BEGIN CAN_MspInit 0 */ /* USER CODE END CAN_MspInit 0 */ /* Peripheral clock enable */ __CAN_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_AF9_CAN; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USER CODE BEGIN CAN_MspInit 1 */ /* USER CODE END CAN_MspInit 1 */ } }
int __start(void) { const volatile uint32_t *src; volatile uint32_t *dest; /* Set up BSS and copy data from flash */ for (src = &_eronly, dest = &_sdata; dest < &_edata;) { *dest++ = *src++; } for (dest = &_sbss; dest < &_ebss;) { *dest++ = 0; } SystemInit(); HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Make sure the flash option bytes are set such that we don't re-enter bootloader mode */ set_dfu_option_bytes(0u); MX_USB_DEVICE_Init(); /* Configure GPIO for the CAN_SILENT signal */ GPIO_InitTypeDef GPIO_InitStruct; /* GPIO Ports Clock Enable */ __GPIOA_CLK_ENABLE(); __GPIOB_CLK_ENABLE(); __CRS_CLK_ENABLE(); /*Configure GPIO pin : PB7 */ GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /**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); /* Configure the bxCAN transceiver */ CAN_HandleTypeDef hcan; __CAN_CLK_ENABLE(); hcan.Instance = CAN; hcan.Init.Mode = CAN_MODE_SILENT; hcan.Init.TTCM = DISABLE; hcan.Init.ABOM = ENABLE; hcan.Init.AWUM = ENABLE; hcan.Init.NART = DISABLE; hcan.Init.RFLM = DISABLE; hcan.Init.TXFP = DISABLE; /* Set the bitrate and init */ set_can_bitrate(&hcan, 1000000u); CanRxMsgTypeDef rx_msg; hcan.pRxMsg = &rx_msg; CanTxMsgTypeDef tx_msg; hcan.pTxMsg = &tx_msg; CAN_FilterConfTypeDef filter; filter.FilterNumber = 0; filter.FilterMode = CAN_FILTERMODE_IDMASK; filter.FilterScale = CAN_FILTERSCALE_32BIT; filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; filter.FilterActivation = ENABLE; filter.BankNumber = 0; filter.FilterMaskIdLow = filter.FilterIdLow = filter.FilterMaskIdHigh = filter.FilterIdHigh = 0; HAL_CAN_ConfigFilter(&hcan, &filter); __HAL_UNLOCK(&hcan); /* Now that USB is active, we need to sync with the 1 kHz SOF packets to tune the HSI48 so it's accurate enough not to disrupt the CAN bus. */ RCC_CRSInitTypeDef crs_config; crs_config.Prescaler = RCC_CRS_SYNC_DIV1; crs_config.Source = RCC_CRS_SYNC_SOURCE_USB; crs_config.Polarity = RCC_CRS_SYNC_POLARITY_RISING; crs_config.ReloadValue = RCC_CRS_RELOADVALUE_DEFAULT; crs_config.ErrorLimitValue = RCC_CRS_ERRORLIMIT_DEFAULT; crs_config.HSI48CalibrationValue = RCC_CRS_HSI48CALIBRATION_DEFAULT; HAL_RCCEx_CRSConfig(&crs_config); /* Don't continue unless we're synced */ while (!(HAL_RCCEx_CRSWaitSynchronization(1000000u) & RCC_CRS_SYNCOK)); while (1) { /* Set up the command record */ size_t i; uint8_t current_cmd; uint8_t current_cmd_data[32]; uint8_t current_cmd_data_length; uint8_t channel_open; current_cmd = current_cmd_data_length = i = 0; channel_open = 0; rx_buffer_length = 0; while (hUsbDevice_0 && hUsbDevice_0->pClassData) { /* If the RX buffer is non-empty, process any commands/messages in it and then acknowledge the transfer to the USB stack */ if (rx_buffer_length) { /* Exit if we've read the entire buffer, or if transmit mailboxes are full and the current command is a transmit. */ for (; i < rx_buffer_length && ((current_cmd != 't' && current_cmd != 'T') || __HAL_CAN_GET_FLAG(&hcan, CAN_FLAG_TME0)); i++) { if (rx_buffer[i] == '\r') { uint8_t *buf = active_buffer ? tx_buffer_1 : tx_buffer_0; /* End of command -- process and reset state */ switch (current_cmd) { case 'S': /* Setup bitrate -- data should be a number from 0 to 8. */ if (current_cmd_data[0] < '0' || current_cmd_data[0] > '8') { buf[active_buffer_length++] = '\a'; } else if (set_can_bitrate( &hcan, bitrate_lookup[current_cmd_data[0] - '0'])) { buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 'O': /* Open channel -- take CAN out of silent mode and start receiving. */ if (!channel_open) { channel_open = 1; set_can_silent(&hcan, 0); buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 'L': /* Open in listen-only -- CAN should already be in silent mode but just make sure. */ if (!channel_open) { channel_open = 1; set_can_silent(&hcan, 1); buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 'C': /* Close channel -- put CAN back in silent mode. */ if (channel_open) { channel_open = 0; set_can_silent(&hcan, 1); buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 'V': /* Hardware version */ buf[active_buffer_length++] = 'V'; buf[active_buffer_length++] = '0'; buf[active_buffer_length++] = '0'; buf[active_buffer_length++] = '0'; buf[active_buffer_length++] = '1'; buf[active_buffer_length++] = '\r'; break; case 'v': /* Major/minor version */ buf[active_buffer_length++] = 'v'; buf[active_buffer_length++] = '0'; buf[active_buffer_length++] = '0'; buf[active_buffer_length++] = '0'; buf[active_buffer_length++] = '1'; buf[active_buffer_length++] = '\r'; break; case 'N': /* Serial number */ buf[active_buffer_length++] = 'N'; buf[active_buffer_length++] = 'F'; buf[active_buffer_length++] = 'F'; buf[active_buffer_length++] = 'F'; buf[active_buffer_length++] = 'F'; buf[active_buffer_length++] = '\r'; break; case 'T': /* Extended message */ if (read_ext_message(&tx_msg, current_cmd_data, current_cmd_data_length) && HAL_CAN_Transmit(&hcan, 0) == HAL_OK) { buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 't': /* Standard message */ if (read_std_message(&tx_msg, current_cmd_data, current_cmd_data_length) && HAL_CAN_Transmit(&hcan, 0) == HAL_OK) { buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 'R': /* Extended RTR */ if (read_ext_rtr(&tx_msg, current_cmd_data, current_cmd_data_length) && HAL_CAN_Transmit(&hcan, 0) == HAL_OK) { buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case 'r': /* Standard RTR */ if (read_std_rtr(&tx_msg, current_cmd_data, current_cmd_data_length) && HAL_CAN_Transmit(&hcan, 0) == HAL_OK) { buf[active_buffer_length++] = '\r'; } else { buf[active_buffer_length++] = '\a'; } break; case '_': /* Bootloader request */ if (current_cmd_data[0] == '_' && current_cmd_data[1] == 'd' && current_cmd_data[2] == 'f' && current_cmd_data[3] == 'u') { /* Set option bytes to force bootloader entry */ set_dfu_option_bytes(1u); NVIC_SystemReset(); } else { buf[active_buffer_length++] = '\a'; } break; case 'F': /* Read status flags -- return 4 hex digits */ case 'Z': /* Timestamp on/off -- 0=off, 1=on */ case 'M': /* Acceptance mask -- 8 hex digits */ case 'm': /* Acceptance value -- 8 hex digits */ case 's': /* Set bitrate register -- 6 hex digits */ default: /* NACK */ buf[active_buffer_length++] = '\a'; break; } current_cmd = current_cmd_data_length = 0; } else if (current_cmd) { /* Command data -- save it */ current_cmd_data[current_cmd_data_length++] = rx_buffer[i]; /* Reset command state if the data is too long */ if (current_cmd_data_length == 32u) { current_cmd = current_cmd_data_length = 0; } } else { /* The first letter of a line is the command type -- don't bother validating as we can't NACK until the data has been received. */ current_cmd = rx_buffer[i]; } } if (i == rx_buffer_length) { /* Mark last packet as received */ rx_buffer_length = i = 0; USBD_CDC_ReceivePacket(hUsbDevice_0); } } /* Check the CAN controller for messages and process them if the channel is open */ if (HAL_CAN_Receive(&hcan, CAN_FIFO0, 0) == HAL_OK && hUsbDevice_0 && channel_open) { /* Format the message and send it to the host. The data format for a standard ID message is: tiiildddddddddddddddd\r The data format for a standard ID RTR is: riii\r The data format for an extended ID message is: Tiiiiiiiildddddddddddddddd\r The data format for an extended ID RTR is: Riiiiiiii\r */ uint8_t *write_location; if (active_buffer_length + EXT_MESSAGE_LEN > TX_BUFFER_SIZE) { /* Reset buffer if we're too far behind -- use worst-case message length for calculation */ active_buffer_length = 0; } write_location = &((active_buffer ? tx_buffer_1 : tx_buffer_0)[active_buffer_length]); if (rx_msg.IDE == CAN_ID_EXT && rx_msg.RTR) { active_buffer_length += write_ext_rtr( write_location, &rx_msg); } else if (rx_msg.IDE == CAN_ID_EXT && !rx_msg.RTR) { active_buffer_length += write_ext_message( write_location, &rx_msg); } else if (rx_msg.IDE == CAN_ID_STD && rx_msg.RTR) { active_buffer_length += write_std_rtr( write_location, &rx_msg); } else if (rx_msg.IDE == CAN_ID_STD && !rx_msg.RTR) { active_buffer_length += write_std_message( write_location, &rx_msg); } } if (!hUsbDevice_0 || !hUsbDevice_0->pClassData) { /* Reset TX buffer if USB is not connected */ active_buffer_length = 0; } else if (active_buffer_length && ((USBD_CDC_HandleTypeDef*)hUsbDevice_0->pClassData)->TxState == 0) { /* Transmit the next buffer if one is available */ CDC_Transmit_FS(active_buffer ? tx_buffer_1 : tx_buffer_0, active_buffer_length); active_buffer_length = 0; active_buffer = active_buffer ? 0 : 1; } } } }