diff --git a/Core/Inc/main.h b/Core/Inc/main.h index efa4647..6f36df3 100644 --- a/Core/Inc/main.h +++ b/Core/Inc/main.h @@ -27,7 +27,6 @@ extern "C" { /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx_hal.h" - /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include diff --git a/Core/Src/main.c b/Core/Src/main.c index bbac8fd..c1ce2fe 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -1,562 +1,564 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : main.c - * @brief : Main program body - ****************************************************************************** - * @attention - * Copyright (c) 2026 STMicroelectronics. - * Copyright (c) 2026 Erick Ahmed. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - ****************************************************************************** - */ -/* USER CODE END Header */ -/* Includes ------------------------------------------------------------------*/ -#include "main.h" -#include "cmsis_os.h" - -/* Private includes ----------------------------------------------------------*/ -/* USER CODE BEGIN Includes */ -#include "canlog.h" -#include "cansend.h" -/* USER CODE END Includes */ - -/* Private typedef -----------------------------------------------------------*/ -/* USER CODE BEGIN PTD */ -/* USER CODE END PTD */ - -/* Private define ------------------------------------------------------------*/ -/* USER CODE BEGIN PD */ - -/* USER CODE END PD */ - -/* Private macro -------------------------------------------------------------*/ -/* USER CODE BEGIN PM */ - -/* USER CODE END PM */ - -/* Private variables ---------------------------------------------------------*/ -CAN_HandleTypeDef hcan1; -CAN_HandleTypeDef hcan2; - -SD_HandleTypeDef hsd; -DMA_HandleTypeDef hdma_sdio_rx; -DMA_HandleTypeDef hdma_sdio_tx; - -UART_HandleTypeDef huart1; - -/* USER CODE BEGIN PV */ -LED_Config led_can1 = {GPIOB, GPIO_PIN_2}; -LED_Config led_can2 = {GPIOB, GPIO_PIN_5}; -LED_Config led_error = {GPIOB, GPIO_PIN_3}; - -osThreadId_t xCAN1rxTask; -osThreadId_t xCAN2rxTask; -osThreadId_t xCAN1LedTask; -osThreadId_t xCAN2LedTask; - -osMessageQueueId_t xCAN1RxQueue; -osMessageQueueId_t xCAN2RxQueue; -osMessageQueueId_t xUARTQueue; - -osSemaphoreId_t xUARTDMASemaphore; -osThreadId_t xUartTask; - -/* USER CODE END PV */ - -/* Private function prototypes -----------------------------------------------*/ -void SystemClock_Config(void); -static void MX_GPIO_Init(void); -static void MX_DMA_Init(void); -static void MX_CAN1_Init(void); -static void MX_CAN2_Init(void); -static void MX_SDIO_SD_Init(void); -static void MX_USART1_UART_Init(void); - -/* USER CODE BEGIN PFP */ -/* USER CODE END PFP */ - -/* Private user code ---------------------------------------------------------*/ -/* USER CODE BEGIN 0 */ - -/* USER CODE END 0 */ - -/** - * @brief The application entry point. - * @retval int - */ -int main(void) -{ - - /* USER CODE BEGIN 1 */ - CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; - ITM->LAR = 0xC5ACCE55; - ITM->TER = 1 << 0; - ITM->TCR = ITM_TCR_ITMENA_Msk | ITM_TCR_SYNCENA_Msk | ITM_TCR_SWOENA_Msk; - DEBUG_PRINT("Booting system\r\n"); - /* USER CODE END 1 */ - - /* MCU Configuration--------------------------------------------------------*/ - - /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ - HAL_Init(); - - /* USER CODE BEGIN Init */ - DEBUG_PRINT("Configuring system clock\r\n"); - - /* USER CODE END Init */ - - /* Configure the system clock */ - SystemClock_Config(); - - /* USER CODE BEGIN SysInit */ - DEBUG_PRINT("Initializing configured peripherals...\r\n"); - /* USER CODE END SysInit */ - - /* Initialize all configured peripherals */ - MX_GPIO_Init(); - MX_DMA_Init(); - MX_CAN1_Init(); - MX_CAN2_Init(); - MX_SDIO_SD_Init(); - MX_USART1_UART_Init(); - /* USER CODE BEGIN 2 */ - DEBUG_PRINT("Initializing CAN bus logger\r\n"); - CAN_Logger_Init(&hcan1, &hcan2); - /* USER CODE END 2 */ - - /* Init scheduler */ - osKernelInitialize(); - - DEBUG_PRINT("Creating RTOS entities\r\n"); - - /* USER CODE BEGIN RTOS_TASKS */ - const osThreadAttr_t CAN1rxAttributes = { - .name = "CAN1rx", - .stack_size = 128 * 4, - .priority = (osPriority_t) osPriorityRealtime1, - }; - const osThreadAttr_t CAN2rxAttributes = { - .name = "CAN2rx", - .stack_size = 128 * 4, - .priority = (osPriority_t) osPriorityRealtime, - }; - const osThreadAttr_t UartLoggerAttributes = { - .name = "UART_Logger", - .stack_size = 256 * 4, - .priority = (osPriority_t) osPriorityHigh, - }; - const osThreadAttr_t LEDHeartbeatCAN1Attributes = { - .name = "LED_HB_CAN1", - .stack_size = 128 * 4, - .priority = (osPriority_t) osPriorityLow1, - }; - const osThreadAttr_t LEDHeartbeatCAN2Attributes = { - .name = "LED_HB_CAN2", - .stack_size = 128 * 4, - .priority = (osPriority_t) osPriorityLow, - }; - /* USER CODE END RTOS_TASKS */ - - /* USER CODE BEGIN RTOS_MUTEX */ - /* USER CODE END RTOS_MUTEX */ - - /* USER CODE BEGIN RTOS_SEMAPHORES */ - xUARTDMASemaphore = osSemaphoreNew(1, 0, NULL); - if (xUARTDMASemaphore == NULL) Error_Handler(); - /* USER CODE END RTOS_SEMAPHORES */ - - /* USER CODE BEGIN RTOS_TIMERS */ - /* USER CODE END RTOS_TIMERS */ - - /* USER CODE BEGIN RTOS_QUEUES */ - xCAN1RxQueue = osMessageQueueNew(64, sizeof(CanMessage_t), NULL); - xCAN2RxQueue = osMessageQueueNew(64, sizeof(CanMessage_t), NULL); - xUARTQueue = osMessageQueueNew(128, sizeof(CanMessage_t), NULL); - - if (xCAN1RxQueue == NULL || xCAN2RxQueue == NULL || xUARTQueue == NULL) Error_Handler(); - /* USER CODE END RTOS_QUEUES */ - - /* USER CODE BEGIN RTOS_THREADS */ - xCAN1rxTask = osThreadNew(vCANListener, &hcan1, &CAN1rxAttributes); - xCAN2rxTask = osThreadNew(vCANListener, &hcan2, &CAN2rxAttributes); - xUartTask = osThreadNew(vUARTLogger, NULL, &UartLoggerAttributes); - xCAN1LedTask = osThreadNew(vLEDHeartbeat, &led_can1, &LEDHeartbeatCAN1Attributes); - xCAN2LedTask = osThreadNew(vLEDHeartbeat, &led_can2, &LEDHeartbeatCAN2Attributes); - /* USER CODE END RTOS_THREADS */ - - /* USER CODE BEGIN RTOS_EVENTS */ - /* USER CODE END RTOS_EVENTS */ - - /* Start scheduler */ - DEBUG_PRINT("Starting RTOS init scheduler\r\n"); - osKernelStart(); - - /* We should never get here as control is now taken by the scheduler */ - - /* Infinite loop */ - /* USER CODE BEGIN WHILE */ - while (1) - { - /* USER CODE END WHILE */ - - /* USER CODE BEGIN 3 */ - DEBUG_PRINT("ERROR: RTOS scheduler crashed!\r\n"); - /* USER CODE END 3 */ - } -} - -/** - * @brief System Clock Configuration - * @retval None - */ -void SystemClock_Config(void) -{ - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - - /** Configure the main internal regulator output voltage - */ - __HAL_RCC_PWR_CLK_ENABLE(); - __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); - - /** Initializes the RCC Oscillators according to the specified parameters - * in the RCC_OscInitTypeDef structure. - */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; - RCC_OscInitStruct.PLL.PLLM = 16; - RCC_OscInitStruct.PLL.PLLN = 336; - RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; - RCC_OscInitStruct.PLL.PLLQ = 7; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) - { - Error_Handler(); - } - - /** Initializes the CPU, AHB and APB buses clocks - */ - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK - |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4; - - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) - { - Error_Handler(); - } -} - -/** - * @brief CAN1 Initialization Function - * @param None - * @retval None - */ -static void MX_CAN1_Init(void) -{ - - /* USER CODE BEGIN CAN1_Init 0 */ - - /* USER CODE END CAN1_Init 0 */ - - /* USER CODE BEGIN CAN1_Init 1 */ - - /* USER CODE END CAN1_Init 1 */ - hcan1.Instance = CAN1; - hcan1.Init.Prescaler = 4; - hcan1.Init.Mode = CAN_MODE_SILENT; - hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ; - hcan1.Init.TimeSeg1 = CAN_BS1_16TQ; - hcan1.Init.TimeSeg2 = CAN_BS2_4TQ; - hcan1.Init.TimeTriggeredMode = DISABLE; - hcan1.Init.AutoBusOff = DISABLE; - hcan1.Init.AutoWakeUp = ENABLE; - hcan1.Init.AutoRetransmission = DISABLE; - hcan1.Init.ReceiveFifoLocked = DISABLE; - hcan1.Init.TransmitFifoPriority = DISABLE; - if (HAL_CAN_Init(&hcan1) != HAL_OK) - { - Error_Handler(); - } - /* USER CODE BEGIN CAN1_Init 2 */ - DEBUG_PRINT("CAN1 initialized!\r\n"); - /* USER CODE END CAN1_Init 2 */ - -} - -/** - * @brief CAN2 Initialization Function - * @param None - * @retval None - */ -static void MX_CAN2_Init(void) -{ - - /* USER CODE BEGIN CAN2_Init 0 */ - - /* USER CODE END CAN2_Init 0 */ - - /* USER CODE BEGIN CAN2_Init 1 */ - - /* USER CODE END CAN2_Init 1 */ - hcan2.Instance = CAN2; - hcan2.Init.Prescaler = 8; - hcan2.Init.Mode = CAN_MODE_SILENT; - hcan2.Init.SyncJumpWidth = CAN_SJW_1TQ; - hcan2.Init.TimeSeg1 = CAN_BS1_16TQ; - hcan2.Init.TimeSeg2 = CAN_BS2_4TQ; - hcan2.Init.TimeTriggeredMode = DISABLE; - hcan2.Init.AutoBusOff = DISABLE; - hcan2.Init.AutoWakeUp = ENABLE; - hcan2.Init.AutoRetransmission = DISABLE; - hcan2.Init.ReceiveFifoLocked = DISABLE; - hcan2.Init.TransmitFifoPriority = DISABLE; - if (HAL_CAN_Init(&hcan2) != HAL_OK) - { - Error_Handler(); - } - /* USER CODE BEGIN CAN2_Init 2 */ - DEBUG_PRINT("CAN2 initialized!\r\n"); - /* USER CODE END CAN2_Init 2 */ - -} - -/** - * @brief SDIO Initialization Function - * @param None - * @retval None - */ -static void MX_SDIO_SD_Init(void) -{ - - /* USER CODE BEGIN SDIO_Init 0 */ - - /* USER CODE END SDIO_Init 0 */ - - /* USER CODE BEGIN SDIO_Init 1 */ - - /* USER CODE END SDIO_Init 1 */ - hsd.Instance = SDIO; - hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; - hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; - hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; - hsd.Init.BusWide = SDIO_BUS_WIDE_1B; - hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; - hsd.Init.ClockDiv = 0; - if (HAL_SD_Init(&hsd) != HAL_OK) - { - Error_Handler(); - } - if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK) - { - Error_Handler(); - } - /* USER CODE BEGIN SDIO_Init 2 */ - DEBUG_PRINT("SDIO initialized!\r\n"); - /* USER CODE END SDIO_Init 2 */ - -} - -/** - * @brief USART1 Initialization Function - * @param None - * @retval None - */ -static void MX_USART1_UART_Init(void) -{ - - /* USER CODE BEGIN USART1_Init 0 */ - - /* USER CODE END USART1_Init 0 */ - - /* USER CODE BEGIN USART1_Init 1 */ - - /* USER CODE END USART1_Init 1 */ - huart1.Instance = USART1; - huart1.Init.BaudRate = 1152000; - huart1.Init.WordLength = UART_WORDLENGTH_8B; - huart1.Init.StopBits = UART_STOPBITS_1; - huart1.Init.Parity = UART_PARITY_NONE; - huart1.Init.Mode = UART_MODE_TX_RX; - huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; - huart1.Init.OverSampling = UART_OVERSAMPLING_16; - if (HAL_UART_Init(&huart1) != HAL_OK) - { - Error_Handler(); - } - /* USER CODE BEGIN USART1_Init 2 */ - DEBUG_PRINT("USART1 initialized!\r\n"); - /* USER CODE END USART1_Init 2 */ - -} - -/** - * Enable DMA controller clock - */ -static void MX_DMA_Init(void) -{ - - /* DMA controller clock enable */ - __HAL_RCC_DMA2_CLK_ENABLE(); - - /* DMA interrupt init */ - /* DMA2_Stream3_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 5, 0); - HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); - /* DMA2_Stream6_IRQn interrupt configuration */ - HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 5, 0); - HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn); - - /* USER CODE BEGIN MX_DMA_Init 1 */ - DEBUG_PRINT("DMA initialized!\r\n"); - /* USER CODE END MX_DMA_Init 1 */ -} - -/** - * @brief GPIO Initialization Function - * @param None - * @retval None - */ -static void MX_GPIO_Init(void) -{ - GPIO_InitTypeDef GPIO_InitStruct = {0}; - /* USER CODE BEGIN MX_GPIO_Init_1 */ - - /* USER CODE END MX_GPIO_Init_1 */ - - /* GPIO Ports Clock Enable */ - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOH_CLK_ENABLE(); - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOD_CLK_ENABLE(); - - /*Configure GPIO pin Output Level */ - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET); - - /*Configure GPIO pins : PC13 PC14 PC15 PC0 - PC1 PC2 PC3 PC4 - PC5 PC6 PC7 */ - GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0 - |GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4 - |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - - /*Configure GPIO pins : PH0 PH1 */ - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); - - /*Configure GPIO pins : PA1 PA2 PA3 PA4 - PA5 PA6 PA7 PA8 - PA11 PA12 */ - GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4 - |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8 - |GPIO_PIN_11|GPIO_PIN_12; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - /*Configure GPIO pins : PB0 PB1 PB2 PB10 - PB11 PB14 PB15 */ - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10 - |GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_15; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - /*Configure GPIO pins : PB5 PB6 PB7 */ - GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - /* USER CODE BEGIN MX_GPIO_Init_2 */ - DEBUG_PRINT("GPIO initialized!\r\n"); - /* USER CODE END MX_GPIO_Init_2 */ -} - -/* USER CODE BEGIN 4 */ -/* USER CODE END 4 */ - -/** - * @brief Period elapsed callback in non blocking mode - * @note This function is called when TIM6 interrupt took place, inside - * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment - * a global variable "uwTick" used as application time base. - * @param htim : TIM handle - * @retval None - */ -void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) -{ - /* USER CODE BEGIN Callback 0 */ - - /* USER CODE END Callback 0 */ - if (htim->Instance == TIM6) - { - HAL_IncTick(); - } - /* USER CODE BEGIN Callback 1 */ - - /* USER CODE END Callback 1 */ -} - -/** - * @brief This function is executed in case of error occurrence. - * @retval None - */ -void Error_Handler(void) -{ - DEBUG_PRINT("ERROR: entering error handler\r\n"); - - /* USER CODE BEGIN Error_Handler_Debug */ - /* User can add his own implementation to report the HAL error return state */ - __disable_irq(); - - //TODO: check if it is necessary to stop FreeRTOS - - uint32_t error_code_can1; - uint32_t error_code_can2; - - if (HAL_CAN_GetState(&hcan1) != HAL_CAN_STATE_READY) error_code_can1 = HAL_CAN_GetError(&hcan1); - if (HAL_CAN_GetState(&hcan2) != HAL_CAN_STATE_READY) error_code_can2 = HAL_CAN_GetError(&hcan2); - - // TODO: write error to SD and/or serial - - HAL_GPIO_WritePin(led_can1.port, led_can1.pin, GPIO_PIN_RESET); - HAL_GPIO_WritePin(led_can2.port, led_can2.pin, GPIO_PIN_RESET); - - while (1) - { - HAL_GPIO_TogglePin(led_error.port, led_error.pin); - HAL_Delay(250); - } - /* USER CODE END Error_Handler_Debug */ -} -#ifdef USE_FULL_ASSERT -/** - * @brief Reports the name of the source file and the source line number - * where the assert_param error has occurred. - * @param file: pointer to the source file name - * @param line: assert_param error line source number - * @retval None - */ -void assert_failed(uint8_t *file, uint32_t line) -{ - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line number, - ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ - /* USER CODE END 6 */ -} -#endif /* USE_FULL_ASSERT */ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * Copyright (c) 2026 STMicroelectronics. + * Copyright (c) 2026 Erick Ahmed. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "cmsis_os.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "canlog.h" +#include "cansend.h" +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +CAN_HandleTypeDef hcan1; +CAN_HandleTypeDef hcan2; + +SD_HandleTypeDef hsd; +DMA_HandleTypeDef hdma_sdio_rx; +DMA_HandleTypeDef hdma_sdio_tx; + +UART_HandleTypeDef huart1; + +/* USER CODE BEGIN PV */ +LED_Config led_can1 = {GPIOB, GPIO_PIN_2}; +LED_Config led_can2 = {GPIOB, GPIO_PIN_5}; +LED_Config led_error = {GPIOB, GPIO_PIN_3}; + +osThreadId_t xCAN1rxTask; +osThreadId_t xCAN2rxTask; +osThreadId_t xCAN1LedTask; +osThreadId_t xCAN2LedTask; + +osMessageQueueId_t xCAN1RxQueue; +osMessageQueueId_t xCAN2RxQueue; +osMessageQueueId_t xUARTQueue; + +osSemaphoreId_t xUARTDMASemaphore; +osThreadId_t xUartTask; + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +static void MX_GPIO_Init(void); +static void MX_DMA_Init(void); +static void MX_CAN1_Init(void); +static void MX_CAN2_Init(void); +static void MX_SDIO_SD_Init(void); +static void MX_USART1_UART_Init(void); + +/* USER CODE BEGIN PFP */ +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + + /* USER CODE BEGIN 1 */ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + ITM->LAR = 0xC5ACCE55; + ITM->TER = 1 << 0; + ITM->TCR = ITM_TCR_ITMENA_Msk | ITM_TCR_SYNCENA_Msk | ITM_TCR_SWOENA_Msk; + DEBUG_PRINT("Booting system\r\n"); + /* USER CODE END 1 */ + + /* MCU Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); + + /* USER CODE BEGIN Init */ + DEBUG_PRINT("Configuring system clock\r\n"); + + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* USER CODE BEGIN SysInit */ + DEBUG_PRINT("Initializing configured peripherals...\r\n"); + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + MX_CAN1_Init(); + MX_CAN2_Init(); + MX_SDIO_SD_Init(); + MX_USART1_UART_Init(); + /* USER CODE BEGIN 2 */ + DEBUG_PRINT("Initializing CAN bus logger\r\n"); + CAN_Logger_Init(&hcan1, &hcan2); + /* USER CODE END 2 */ + + /* Init scheduler */ + osKernelInitialize(); + + DEBUG_PRINT("Creating RTOS entities\r\n"); + + /* USER CODE BEGIN RTOS_TASKS */ + const osThreadAttr_t CAN1rxAttributes = { + .name = "CAN1rx", + .stack_size = 128 * 4, + .priority = (osPriority_t) osPriorityRealtime1, + }; + const osThreadAttr_t CAN2rxAttributes = { + .name = "CAN2rx", + .stack_size = 128 * 4, + .priority = (osPriority_t) osPriorityRealtime, + }; + const osThreadAttr_t UartLoggerAttributes = { + .name = "UART_Logger", + .stack_size = 256 * 4, + .priority = (osPriority_t) osPriorityHigh, + }; + const osThreadAttr_t LEDHeartbeatCAN1Attributes = { + .name = "LED_HB_CAN1", + .stack_size = 128 * 4, + .priority = (osPriority_t) osPriorityLow1, + }; + const osThreadAttr_t LEDHeartbeatCAN2Attributes = { + .name = "LED_HB_CAN2", + .stack_size = 128 * 4, + .priority = (osPriority_t) osPriorityLow, + }; + /* USER CODE END RTOS_TASKS */ + + /* USER CODE BEGIN RTOS_MUTEX */ + /* USER CODE END RTOS_MUTEX */ + + /* USER CODE BEGIN RTOS_SEMAPHORES */ + xUARTDMASemaphore = osSemaphoreNew(1, 0, NULL); + if (xUARTDMASemaphore == NULL) Error_Handler(); + /* USER CODE END RTOS_SEMAPHORES */ + + /* USER CODE BEGIN RTOS_TIMERS */ + /* USER CODE END RTOS_TIMERS */ + + /* USER CODE BEGIN RTOS_QUEUES */ + xCAN1RxQueue = osMessageQueueNew(64, sizeof(CanMessage_t), NULL); + xCAN2RxQueue = osMessageQueueNew(64, sizeof(CanMessage_t), NULL); + xUARTQueue = osMessageQueueNew(128, sizeof(CanMessage_t), NULL); + + if (xCAN1RxQueue == NULL || xCAN2RxQueue == NULL || xUARTQueue == NULL) Error_Handler(); + /* USER CODE END RTOS_QUEUES */ + + /* USER CODE BEGIN RTOS_THREADS */ + xCAN1rxTask = osThreadNew(vCANListener, &hcan1, &CAN1rxAttributes); + xCAN2rxTask = osThreadNew(vCANListener, &hcan2, &CAN2rxAttributes); + xUartTask = osThreadNew(vUARTLogger, NULL, &UartLoggerAttributes); + xCAN1LedTask = osThreadNew(vLEDHeartbeat, &led_can1, &LEDHeartbeatCAN1Attributes); + xCAN2LedTask = osThreadNew(vLEDHeartbeat, &led_can2, &LEDHeartbeatCAN2Attributes); + /* USER CODE END RTOS_THREADS */ + + /* USER CODE BEGIN RTOS_EVENTS */ + /* USER CODE END RTOS_EVENTS */ + + /* Start scheduler */ + DEBUG_PRINT("Starting RTOS init scheduler\r\n"); + osKernelStart(); + + /* We should never get here as control is now taken by the scheduler */ + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) + { + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + DEBUG_PRINT("ERROR: RTOS scheduler crashed!\r\n"); + /* USER CODE END 3 */ + } +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + + /** Configure the main internal regulator output voltage + */ + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLM = 16; + RCC_OscInitStruct.PLL.PLLN = 336; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 7; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(); + } + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) + { + Error_Handler(); + } +} + +/** + * @brief CAN1 Initialization Function + * @param None + * @retval None + */ +static void MX_CAN1_Init(void) +{ + + /* USER CODE BEGIN CAN1_Init 0 */ + + /* USER CODE END CAN1_Init 0 */ + + /* USER CODE BEGIN CAN1_Init 1 */ + + /* USER CODE END CAN1_Init 1 */ + hcan1.Instance = CAN1; + hcan1.Init.Prescaler = 4; + hcan1.Init.Mode = CAN_MODE_SILENT; + hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ; + hcan1.Init.TimeSeg1 = CAN_BS1_16TQ; + hcan1.Init.TimeSeg2 = CAN_BS2_4TQ; + hcan1.Init.TimeTriggeredMode = DISABLE; + hcan1.Init.AutoBusOff = DISABLE; + hcan1.Init.AutoWakeUp = ENABLE; + hcan1.Init.AutoRetransmission = DISABLE; + hcan1.Init.ReceiveFifoLocked = DISABLE; + hcan1.Init.TransmitFifoPriority = DISABLE; + if (HAL_CAN_Init(&hcan1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN CAN1_Init 2 */ + DEBUG_PRINT("CAN1 initialized!\r\n"); + /* USER CODE END CAN1_Init 2 */ + +} + +/** + * @brief CAN2 Initialization Function + * @param None + * @retval None + */ +static void MX_CAN2_Init(void) +{ + + /* USER CODE BEGIN CAN2_Init 0 */ + + /* USER CODE END CAN2_Init 0 */ + + /* USER CODE BEGIN CAN2_Init 1 */ + + /* USER CODE END CAN2_Init 1 */ + hcan2.Instance = CAN2; + hcan2.Init.Prescaler = 8; + hcan2.Init.Mode = CAN_MODE_SILENT; + hcan2.Init.SyncJumpWidth = CAN_SJW_1TQ; + hcan2.Init.TimeSeg1 = CAN_BS1_16TQ; + hcan2.Init.TimeSeg2 = CAN_BS2_4TQ; + hcan2.Init.TimeTriggeredMode = DISABLE; + hcan2.Init.AutoBusOff = DISABLE; + hcan2.Init.AutoWakeUp = ENABLE; + hcan2.Init.AutoRetransmission = DISABLE; + hcan2.Init.ReceiveFifoLocked = DISABLE; + hcan2.Init.TransmitFifoPriority = DISABLE; + if (HAL_CAN_Init(&hcan2) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN CAN2_Init 2 */ + DEBUG_PRINT("CAN2 initialized!\r\n"); + /* USER CODE END CAN2_Init 2 */ + +} + +/** + * @brief SDIO Initialization Function + * @param None + * @retval None + */ +static void MX_SDIO_SD_Init(void) +{ + + /* USER CODE BEGIN SDIO_Init 0 */ + + /* USER CODE END SDIO_Init 0 */ + + /* USER CODE BEGIN SDIO_Init 1 */ + + /* USER CODE END SDIO_Init 1 */ + hsd.Instance = SDIO; + hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; + hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; + hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; + hsd.Init.BusWide = SDIO_BUS_WIDE_1B; + hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; + hsd.Init.ClockDiv = 0; + if (HAL_SD_Init(&hsd) != HAL_OK) + { + Error_Handler(); + } + if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN SDIO_Init 2 */ + DEBUG_PRINT("SDIO initialized!\r\n"); + /* USER CODE END SDIO_Init 2 */ + +} + +/** + * @brief USART1 Initialization Function + * @param None + * @retval None + */ +static void MX_USART1_UART_Init(void) +{ + + /* USER CODE BEGIN USART1_Init 0 */ + + /* USER CODE END USART1_Init 0 */ + + /* USER CODE BEGIN USART1_Init 1 */ + + /* USER CODE END USART1_Init 1 */ + huart1.Instance = USART1; + huart1.Init.BaudRate = 1152000; + huart1.Init.WordLength = UART_WORDLENGTH_8B; + huart1.Init.StopBits = UART_STOPBITS_1; + huart1.Init.Parity = UART_PARITY_NONE; + huart1.Init.Mode = UART_MODE_TX_RX; + huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart1.Init.OverSampling = UART_OVERSAMPLING_16; + if (HAL_UART_Init(&huart1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN USART1_Init 2 */ + DEBUG_PRINT("USART1 initialized!\r\n"); + /* USER CODE END USART1_Init 2 */ + +} + +/** + * Enable DMA controller clock + */ +static void MX_DMA_Init(void) +{ + + /* DMA controller clock enable */ + __HAL_RCC_DMA2_CLK_ENABLE(); + + /* DMA interrupt init */ + /* DMA2_Stream3_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); + /* DMA2_Stream6_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn); + + /* USER CODE BEGIN MX_DMA_Init 1 */ + DEBUG_PRINT("DMA initialized!\r\n"); + /* USER CODE END MX_DMA_Init 1 */ +} + +/** + * @brief GPIO Initialization Function + * @param None + * @retval None + */ +static void MX_GPIO_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + /* USER CODE BEGIN MX_GPIO_Init_1 */ + + /* USER CODE END MX_GPIO_Init_1 */ + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET); + + /*Configure GPIO pins : PC13 PC14 PC15 PC0 + PC1 PC2 PC3 PC4 + PC5 PC6 PC7 */ + GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0 + |GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4 + |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /*Configure GPIO pins : PH0 PH1 */ + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); + + /*Configure GPIO pins : PA0 PA1 PA2 PA3 + PA4 PA5 PA6 PA7 + PA8 PA11 PA12 PA15 */ + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 + |GPIO_PIN_8|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_15; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /*Configure GPIO pins : PB0 PB1 PB2 PB10 + PB11 PB14 PB15 PB3 + PB4 */ + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10 + |GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_3 + |GPIO_PIN_4; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /*Configure GPIO pins : PB5 PB6 PB7 */ + GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* USER CODE BEGIN MX_GPIO_Init_2 */ + DEBUG_PRINT("GPIO initialized!\r\n"); + /* USER CODE END MX_GPIO_Init_2 */ +} + +/* USER CODE BEGIN 4 */ +/* USER CODE END 4 */ + +/** + * @brief Period elapsed callback in non blocking mode + * @note This function is called when TIM6 interrupt took place, inside + * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment + * a global variable "uwTick" used as application time base. + * @param htim : TIM handle + * @retval None + */ +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + /* USER CODE BEGIN Callback 0 */ + + /* USER CODE END Callback 0 */ + if (htim->Instance == TIM6) + { + HAL_IncTick(); + } + /* USER CODE BEGIN Callback 1 */ + + /* USER CODE END Callback 1 */ +} + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + DEBUG_PRINT("ERROR: entering error handler\r\n"); + + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + __disable_irq(); + + //TODO: check if it is necessary to stop FreeRTOS + + uint32_t error_code_can1; + uint32_t error_code_can2; + + if (HAL_CAN_GetState(&hcan1) != HAL_CAN_STATE_READY) error_code_can1 = HAL_CAN_GetError(&hcan1); + if (HAL_CAN_GetState(&hcan2) != HAL_CAN_STATE_READY) error_code_can2 = HAL_CAN_GetError(&hcan2); + + // TODO: write error to SD and/or serial + + HAL_GPIO_WritePin(led_can1.port, led_can1.pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(led_can2.port, led_can2.pin, GPIO_PIN_RESET); + + while (1) + { + HAL_GPIO_TogglePin(led_error.port, led_error.pin); + HAL_Delay(250); + } + /* USER CODE END Error_Handler_Debug */ +} +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/can_logger.ioc b/can_logger.ioc index 6a0354e..d6945da 100644 --- a/can_logger.ioc +++ b/can_logger.ioc @@ -68,30 +68,26 @@ Mcu.IP8=USART1 Mcu.IPNb=9 Mcu.Name=STM32F405RGTx Mcu.Package=LQFP64 -Mcu.Pin0=PA0-WKUP -Mcu.Pin1=PB12 -Mcu.Pin10=PC10 -Mcu.Pin11=PC11 -Mcu.Pin12=PC12 -Mcu.Pin13=PD2 -Mcu.Pin14=PB3 -Mcu.Pin15=PB4 -Mcu.Pin16=PB5 -Mcu.Pin17=PB6 -Mcu.Pin18=PB7 -Mcu.Pin19=PB8 -Mcu.Pin2=PB13 -Mcu.Pin20=PB9 -Mcu.Pin21=VP_FREERTOS_VS_CMSIS_V2 -Mcu.Pin22=VP_SYS_VS_tim6 -Mcu.Pin3=PC8 -Mcu.Pin4=PC9 -Mcu.Pin5=PA9 -Mcu.Pin6=PA10 -Mcu.Pin7=PA13 -Mcu.Pin8=PA14 -Mcu.Pin9=PA15 -Mcu.PinsNb=23 +Mcu.Pin0=PB12 +Mcu.Pin1=PB13 +Mcu.Pin10=PC12 +Mcu.Pin11=PD2 +Mcu.Pin12=PB5 +Mcu.Pin13=PB6 +Mcu.Pin14=PB7 +Mcu.Pin15=PB8 +Mcu.Pin16=PB9 +Mcu.Pin17=VP_FREERTOS_VS_CMSIS_V2 +Mcu.Pin18=VP_SYS_VS_tim6 +Mcu.Pin2=PC8 +Mcu.Pin3=PC9 +Mcu.Pin4=PA9 +Mcu.Pin5=PA10 +Mcu.Pin6=PA13 +Mcu.Pin7=PA14 +Mcu.Pin8=PC10 +Mcu.Pin9=PC11 +Mcu.PinsNb=19 Mcu.ThirdPartyNb=0 Mcu.UserConstants= Mcu.UserName=STM32F405RGTx @@ -117,26 +113,18 @@ NVIC.TIM6_DAC_IRQn=true\:15\:0\:false\:false\:true\:false\:false\:true\:true NVIC.TimeBase=TIM6_DAC_IRQn NVIC.TimeBaseIP=TIM6 NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false -PA0-WKUP.Mode=SYS_WakeUp0 -PA0-WKUP.Signal=SYS_WKUP PA10.Mode=Asynchronous PA10.Signal=USART1_RX -PA13.Mode=JTAG_5_pins +PA13.Mode=Serial_Wire PA13.Signal=SYS_JTMS-SWDIO -PA14.Mode=JTAG_5_pins +PA14.Mode=Serial_Wire PA14.Signal=SYS_JTCK-SWCLK -PA15.Mode=JTAG_5_pins -PA15.Signal=SYS_JTDI PA9.Mode=Asynchronous PA9.Signal=USART1_TX PB12.Mode=CAN_Activate PB12.Signal=CAN2_RX PB13.Mode=CAN_Activate PB13.Signal=CAN2_TX -PB3.Mode=JTAG_5_pins -PB3.Signal=SYS_JTDO-SWO -PB4.Mode=JTAG_5_pins -PB4.Signal=SYS_JTRST PB5.Locked=true PB5.Signal=GPIO_Output PB6.Locked=true