├── .DS_Store ├── .gitattributes ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .readthedocs.yaml ├── bootloader ├── .DS_Store ├── Core │ ├── Inc │ │ ├── bootloader.h │ │ ├── can.h │ │ ├── main.h │ │ ├── stm32g4xx_hal_conf.h │ │ ├── stm32g4xx_it.h │ │ └── working.txt │ └── Src │ │ ├── bootloader.c │ │ ├── can.c │ │ ├── main.c │ │ ├── stm32g4xx_hal_msp.c │ │ ├── stm32g4xx_hal_timebase_tim.c │ │ ├── stm32g4xx_it.c │ │ └── system_stm32g4xx.c ├── Makefile ├── STM32-for-VSCode.config.yaml ├── STM32G431CBUx_FLASH.ld ├── STM32Make.make ├── USB_Device │ ├── App │ │ ├── usb_device.c │ │ ├── usb_device.h │ │ ├── usbd_cdc_if.c │ │ ├── usbd_cdc_if.h │ │ ├── usbd_desc.c │ │ └── usbd_desc.h │ └── Target │ │ ├── usbd_conf.c │ │ └── usbd_conf.h ├── openocd.cfg ├── python │ ├── 16_bit_aligned.hex │ ├── convert_hex.py │ ├── enter_app.py │ ├── enter_bootloader.py │ ├── flash_CAN.py │ ├── flash_USB.py │ ├── progress_bar_test.py │ ├── read_hex.py │ ├── send_hex.py │ └── stm32bootloader.py └── startup_stm32g431xx.s ├── docs ├── .DS_Store ├── Doxyfile.in ├── Makefile ├── conf.py ├── firmware │ ├── app.md │ ├── comms.md │ ├── drive.md │ ├── foc.md │ └── index.md ├── hardware │ ├── index.md │ ├── known-faults.md │ └── media │ │ ├── components.jpg │ │ ├── connectors.jpg │ │ └── drive-front-back.jpg ├── index.md ├── make.bat └── requirements.txt ├── firmware ├── .DS_Store ├── .mxproject ├── 50x50_DRIVE.ioc ├── Core │ ├── .DS_Store │ ├── Inc │ │ ├── FreeRTOSConfig.h │ │ ├── app.h │ │ ├── app_timers.h │ │ ├── comms.h │ │ ├── comms_msgs.h │ │ ├── drive.h │ │ ├── foc.h │ │ ├── led.h │ │ ├── main.h │ │ ├── sensors.h │ │ ├── stm32g4xx_hal_conf.h │ │ ├── stm32g4xx_it.h │ │ ├── trig_luts.h │ │ └── utils.h │ └── Src │ │ ├── app.c │ │ ├── app_freertos.c │ │ ├── app_timers.c │ │ ├── comms.c │ │ ├── drive.c │ │ ├── foc.c │ │ ├── led.c │ │ ├── main.c │ │ ├── sensors.c │ │ ├── stm32g4xx_hal_msp.c │ │ ├── stm32g4xx_hal_timebase_tim.c │ │ ├── stm32g4xx_it.c │ │ ├── system_stm32g4xx.c │ │ ├── trig_luts.c │ │ └── utils.c ├── Makefile ├── STM32-for-VSCode.config.yaml ├── STM32G431CBUx_FLASH.ld ├── STM32Make.make ├── USB_Device │ ├── App │ │ ├── usb_device.c │ │ ├── usb_device.h │ │ ├── usbd_cdc_if.c │ │ ├── usbd_cdc_if.h │ │ ├── usbd_desc.c │ │ └── usbd_desc.h │ └── Target │ │ ├── usbd_conf.c │ │ └── usbd_conf.h ├── openocd.cfg ├── python │ └── current_test.ipynb └── startup_stm32g431xx.s └── readme.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LegoYoda112/BLDC_Driver/ad5e74cb48fdc431fb3d7c20c6390ad6ad415936/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Makefile CI 2 | 3 | on: 4 | push: 5 | branches: [ "dev-build" ] 6 | pull_request: 7 | branches: [ "dev-build" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | 17 | - name: Install build tools 18 | run: sudo apt install -y gcc-arm-none-eabi gdb-arm-none-eabi 19 | 20 | - name: Build bootloader 21 | run: cd bootloader && make -j 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | firmware/Drivers/CMSIS 3 | firmware/Drivers/STM32G4xx_HAL_Driver 4 | firmware/Middlewares/ST 5 | firmware/Middlewares/Third_Party/FreeRTOS 6 | 7 | bootloader/Drivers/CMSIS 8 | bootloader/Drivers/STM32G4xx_HAL_Driver 9 | bootloader/Middlewares/ST 10 | bootloader/Middlewares/Third_Party/FreeRTOS 11 | 12 | _build 13 | _static 14 | _templates 15 | _doxygen_build 16 | 17 | __pycache__ 18 | 19 | .vscode -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file for Sphinx projects 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | # Required 5 | version: 2 6 | 7 | # Set the OS, Python version and other tools you might need 8 | build: 9 | os: ubuntu-22.04 10 | tools: 11 | python: "3.12" 12 | # You can also specify other tool versions: 13 | # nodejs: "20" 14 | # rust: "1.70" 15 | # golang: "1.20" 16 | 17 | # Build documentation in the "docs/" directory with Sphinx 18 | sphinx: 19 | configuration: docs/conf.py 20 | # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs 21 | # builder: "dirhtml" 22 | # Fail on all warnings to avoid broken references 23 | # fail_on_warning: true 24 | 25 | # Optionally build your docs in additional formats such as PDF and ePub 26 | # formats: 27 | # - pdf 28 | # - epub 29 | 30 | # Optional but recommended, declare the Python requirements required 31 | # to build your documentation 32 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 33 | python: 34 | install: 35 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /bootloader/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LegoYoda112/BLDC_Driver/ad5e74cb48fdc431fb3d7c20c6390ad6ad415936/bootloader/.DS_Store -------------------------------------------------------------------------------- /bootloader/Core/Inc/bootloader.h: -------------------------------------------------------------------------------- 1 | #ifndef BOOTLOADER_H 2 | #define BOOTLOADER_H 3 | 4 | #include "main.h" 5 | 6 | ///////////// Externs in 7 | extern FDCAN_HandleTypeDef hfdcan1; 8 | extern uint8_t TxData[8]; 9 | extern FDCAN_TxHeaderTypeDef TxHeader; 10 | 11 | ///////////// Defines 12 | #define APP_START_ADDR 0x8008000 13 | #define APP_END_ADDR (0x8008000 + 46 * FLASH_PAGE_SIZE - 1) 14 | #define ADDR_FLASH_PAGE_63 ((uint32_t)0x0801F800) 15 | 16 | ///////////// Variables 17 | // Bootloader state variable 18 | enum bootloaderState{ 19 | init, 20 | idle, 21 | flashing 22 | }; 23 | 24 | extern enum bootloaderState bootloader_state; 25 | 26 | ///////////// Functions 27 | /** 28 | * @brief Called after peripherals have been initted 29 | * branches into running app code, or running the rest 30 | * of the bootloader code. 31 | * 32 | */ 33 | void bootloader_init(); 34 | 35 | /** 36 | * @brief Called in main.c while loop FDCAN1 and LED GPIO pins will have been initted. 37 | * 38 | * @note 39 | * Test 40 | * 41 | */ 42 | void bootloader_loop(); 43 | 44 | /** 45 | * Erases app flash (in preparation for flashing). 46 | * 47 | * @note 48 | * Erases pages between 0x8008000 (page 16) to 0x0801F800 49 | * (page 63) 50 | * 51 | */ 52 | void erase_flash(); 53 | 54 | /** 55 | * @brief DeInits peripherals and jumps processor to 56 | * 0x8008000 57 | * 58 | */ 59 | void bootloader_jump_to_user_app(void); 60 | 61 | /** 62 | * @brief Called when USB interface reaches a '\\r' character 63 | * 64 | * @param Buf Array of received characters 65 | * @param Len Length of buffer 66 | */ 67 | void process_USB_rx(uint8_t* Buf, uint32_t *Len); 68 | 69 | 70 | void process_CAN_rx(FDCAN_RxHeaderTypeDef *Rxheader, uint8_t RxData[]); 71 | 72 | #endif -------------------------------------------------------------------------------- /bootloader/Core/Inc/can.h: -------------------------------------------------------------------------------- 1 | #ifndef CAN_H 2 | #define CAN_H 3 | 4 | #include "main.h" 5 | #include "bootloader.h" 6 | 7 | extern FDCAN_HandleTypeDef hfdcan1; 8 | extern uint8_t TxData[8]; 9 | extern FDCAN_TxHeaderTypeDef TxHeader; 10 | 11 | enum canBitrate { 12 | _500Kbs = 6, 13 | _1000Kbs = 8 14 | }; 15 | 16 | void init_and_start_can(); 17 | void can_set_500kbs(); 18 | void can_set_1000kbs(); 19 | 20 | void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs); 21 | 22 | #endif -------------------------------------------------------------------------------- /bootloader/Core/Inc/main.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : main.h 5 | * @brief : Header for main.c file. 6 | * This file contains the common defines of the application. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __MAIN_H 23 | #define __MAIN_H 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Includes ------------------------------------------------------------------*/ 30 | #include "stm32g4xx_hal.h" 31 | 32 | /* Private includes ----------------------------------------------------------*/ 33 | /* USER CODE BEGIN Includes */ 34 | 35 | /* USER CODE END Includes */ 36 | 37 | /* Exported types ------------------------------------------------------------*/ 38 | /* USER CODE BEGIN ET */ 39 | 40 | /* USER CODE END ET */ 41 | 42 | /* Exported constants --------------------------------------------------------*/ 43 | /* USER CODE BEGIN EC */ 44 | 45 | /* USER CODE END EC */ 46 | 47 | /* Exported macro ------------------------------------------------------------*/ 48 | /* USER CODE BEGIN EM */ 49 | 50 | /* USER CODE END EM */ 51 | 52 | /* Exported functions prototypes ---------------------------------------------*/ 53 | void Error_Handler(void); 54 | 55 | /* USER CODE BEGIN EFP */ 56 | 57 | /* USER CODE END EFP */ 58 | 59 | /* Private defines -----------------------------------------------------------*/ 60 | #define DIP_3_Pin GPIO_PIN_15 61 | #define DIP_3_GPIO_Port GPIOC 62 | #define LED_R_Pin GPIO_PIN_2 63 | #define LED_R_GPIO_Port GPIOA 64 | #define LED_G_Pin GPIO_PIN_3 65 | #define LED_G_GPIO_Port GPIOA 66 | #define LED_B_Pin GPIO_PIN_4 67 | #define LED_B_GPIO_Port GPIOA 68 | 69 | /* USER CODE BEGIN Private defines */ 70 | 71 | /* USER CODE END Private defines */ 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif /* __MAIN_H */ 78 | -------------------------------------------------------------------------------- /bootloader/Core/Inc/stm32g4xx_it.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file stm32g4xx_it.h 5 | * @brief This file contains the headers of the interrupt handlers. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2023 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file 13 | * in the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | * 16 | ****************************************************************************** 17 | */ 18 | /* USER CODE END Header */ 19 | 20 | /* Define to prevent recursive inclusion -------------------------------------*/ 21 | #ifndef __STM32G4xx_IT_H 22 | #define __STM32G4xx_IT_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* Private includes ----------------------------------------------------------*/ 29 | /* USER CODE BEGIN Includes */ 30 | 31 | /* USER CODE END Includes */ 32 | 33 | /* Exported types ------------------------------------------------------------*/ 34 | /* USER CODE BEGIN ET */ 35 | 36 | /* USER CODE END ET */ 37 | 38 | /* Exported constants --------------------------------------------------------*/ 39 | /* USER CODE BEGIN EC */ 40 | 41 | /* USER CODE END EC */ 42 | 43 | /* Exported macro ------------------------------------------------------------*/ 44 | /* USER CODE BEGIN EM */ 45 | 46 | /* USER CODE END EM */ 47 | 48 | /* Exported functions prototypes ---------------------------------------------*/ 49 | void NMI_Handler(void); 50 | void HardFault_Handler(void); 51 | void MemManage_Handler(void); 52 | void BusFault_Handler(void); 53 | void UsageFault_Handler(void); 54 | void SVC_Handler(void); 55 | void DebugMon_Handler(void); 56 | void PendSV_Handler(void); 57 | void SysTick_Handler(void); 58 | void USB_LP_IRQHandler(void); 59 | void FDCAN1_IT0_IRQHandler(void); 60 | void TIM2_IRQHandler(void); 61 | /* USER CODE BEGIN EFP */ 62 | 63 | /* USER CODE END EFP */ 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif /* __STM32G4xx_IT_H */ 70 | -------------------------------------------------------------------------------- /bootloader/Core/Src/bootloader.c: -------------------------------------------------------------------------------- 1 | #include "bootloader.h" 2 | #include "usbd_cdc.h" 3 | #include "usbd_cdc_if.h" 4 | #include "usbd_conf.h" 5 | #include "stdbool.h" 6 | 7 | #include "can.h" 8 | 9 | unsigned char __attribute__((section(".bootBlockRAM"))) boot_bits[10]; 10 | 11 | // Grab usb device pointer 12 | extern USBD_HandleTypeDef hUsbDeviceFS; 13 | 14 | enum bootloaderState bootloader_state; 15 | typedef void (*pFunction)(void); 16 | 17 | uint32_t FirstPage = 0, NbOfPages = 0; 18 | uint32_t Address = 0, PageError = 0; 19 | __IO uint32_t MemoryProgramStatus = 0; 20 | __IO uint64_t data64 = 0; 21 | 22 | static FLASH_EraseInitTypeDef EraseInitStruct; 23 | 24 | bool flashing_firmware = false; 25 | uint8_t words_ready = 0; 26 | uint64_t double_word = 0; 27 | uint8_t null_counter = 0; 28 | 29 | static uint32_t GetPage(uint32_t Addr) 30 | { 31 | return (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;; 32 | } 33 | 34 | int CAN_Transmit_Safe(FDCAN_TxHeaderTypeDef *TxHeader, uint8_t *TxData) 35 | { 36 | // If we have filled up the mailboxes, return early, CAN is not connected 37 | if(HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) == 0){ 38 | // drive_state == drive_state_idle; 39 | return 0; 40 | } 41 | 42 | if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, TxHeader, TxData) != HAL_OK) 43 | { 44 | Error_Handler(); 45 | } 46 | return 1; 47 | } 48 | 49 | void can_ack(){ 50 | TxData[0] = 'O'; 51 | TxData[1] = 'K'; 52 | TxHeader.Identifier = 69; 53 | TxHeader.DataLength = FDCAN_DLC_BYTES_2; 54 | CAN_Transmit_Safe(&TxHeader, TxData); 55 | } 56 | 57 | void process_CAN_rx(FDCAN_RxHeaderTypeDef *RxHeader, uint8_t RxData[]){ 58 | 59 | if(RxHeader->Identifier == 69){ 60 | if(RxHeader->DataLength == FDCAN_DLC_BYTES_0){ 61 | flashing_firmware = false; 62 | } 63 | 64 | if(flashing_firmware){ 65 | __disable_irq(); 66 | double_word = 0; 67 | for(int i = 0; i < 8; i++){ 68 | double_word = double_word | ((uint64_t)RxData[i] << (i * 8)); 69 | } 70 | 71 | // Calculate flash address 72 | uint32_t offset_address = (uint32_t)APP_START_ADDR + Address; 73 | 74 | // Flash 75 | HAL_FLASH_Unlock(); 76 | if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, offset_address, double_word) != HAL_OK){ 77 | Error_Handler(); 78 | } 79 | HAL_FLASH_Lock(); 80 | __enable_irq(); 81 | 82 | Address += 8; 83 | } 84 | 85 | ////////// Clear memory 86 | if(RxData[0] == 'C' && RxData[1] == 'L' && RxData[2] == 'R'){ 87 | erase_flash(); 88 | Address = 0; 89 | flashing_firmware = true; 90 | } 91 | 92 | ////////// Jump to app 93 | if(RxData[0] == 'A' && RxData[1] == 'P' && RxData[2] == 'P'){ 94 | // Set ram blocks to request app to run 95 | boot_bits[0] = 'A'; 96 | boot_bits[1] = 'P'; 97 | boot_bits[2] = 'P'; 98 | can_ack(); 99 | HAL_NVIC_SystemReset(); 100 | } 101 | 102 | 103 | can_ack(); 104 | } 105 | } 106 | 107 | void process_USB_rx(uint8_t* Buf, uint32_t *Len){ 108 | __disable_irq(); 109 | 110 | ////////// Clear 111 | if(Buf[0] == 'C' && Buf[1] == 'L' && Buf[2] == 'R'){ 112 | erase_flash(); 113 | Address = 0; 114 | } 115 | 116 | ////////// Jump to app 117 | if(Buf[0] == 'A' && Buf[1] == 'P' && Buf[2] == 'P'){ 118 | // Set ram blocks to request bootloader to run 119 | boot_bits[0] = 'A'; 120 | boot_bits[1] = 'P'; 121 | boot_bits[2] = 'P'; 122 | HAL_NVIC_SystemReset(); 123 | // bootloader_jump_to_user_app(); 124 | } 125 | 126 | // Receive ihex data 127 | if(Buf[0] == ':'){ 128 | char record_substring[3]; 129 | strncpy(record_substring, Buf + (uint32_t)7, 2); 130 | volatile uint32_t record_type = strtol(record_substring, NULL, 16); 131 | 132 | // Process data record 133 | if(record_substring[0] == '0' && record_substring[1] == '0') { 134 | 135 | // Hardcode data length 136 | uint16_t data_length = 16; 137 | uint8_t data[16]; 138 | // Record strings are 16 byte long = 2x 64bit double words 139 | uint64_t double_word_1 = 0; 140 | uint64_t double_word_2 = 0; 141 | 142 | // Extract data array from hex string and fill double words 143 | for(int i = 0; i < data_length; i++){ 144 | 145 | // Convert hex byte to uint8 146 | char data_substring[3]; 147 | strncpy(data_substring, Buf + 9 + 2 * i, 2); 148 | data_substring[2] = '\0'; 149 | data[i] = strtol(data_substring, NULL, 16); 150 | 151 | // Fill double_word_1 152 | if(i < 8){ 153 | double_word_1 = double_word_1 | ((uint64_t)data[i] << i * 8); 154 | }else{ // Fill double_word_2 155 | double_word_2 = double_word_2 | ((uint64_t)data[i] << (i - 8) * 8); 156 | } 157 | } 158 | 159 | // Calculate flash address 160 | uint32_t offset_address = (uint32_t)APP_START_ADDR + Address; 161 | 162 | // Flash two double words 163 | HAL_FLASH_Unlock(); 164 | if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, offset_address, double_word_1) != HAL_OK){ 165 | Error_Handler(); 166 | } 167 | if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, offset_address + 0x08, double_word_2) != HAL_OK){ 168 | Error_Handler(); 169 | } 170 | HAL_FLASH_Lock(); 171 | 172 | // Increment address 173 | Address += 16; 174 | } 175 | 176 | } 177 | 178 | uint8_t *data = "OK\r"; 179 | CDC_Transmit_FS(data, strlen(data)); 180 | __enable_irq(); 181 | } 182 | 183 | 184 | void bootloader_jump_to_user_app(void) 185 | { 186 | void (*app_reset_handler)(void); 187 | 188 | // DeInit all 189 | HAL_GPIO_DeInit(LED_R_GPIO_Port, LED_R_Pin); 190 | HAL_GPIO_DeInit(LED_G_GPIO_Port, LED_G_Pin); 191 | HAL_GPIO_DeInit(LED_B_GPIO_Port, LED_B_Pin); 192 | HAL_GPIO_DeInit(DIP_3_GPIO_Port, DIP_3_Pin); 193 | 194 | USBD_DeInit(&hUsbDeviceFS); 195 | USBD_LL_DeInit(&hUsbDeviceFS); 196 | 197 | HAL_FDCAN_DeInit(&hfdcan1); 198 | HAL_RCC_DeInit(); 199 | HAL_DeInit(); 200 | 201 | SysTick->CTRL = 0; 202 | SysTick->LOAD = 0; 203 | SysTick->VAL = 0; 204 | 205 | // Disable interrupts 206 | __set_PRIMASK(1); 207 | __disable_irq(); 208 | 209 | // SCB->VTOR = FLASH_SECTOR2_BASE_ADDRESS; //0x080080000 210 | 211 | // Set main stack pointer 212 | uint32_t msp_value = *(__IO uint32_t *)APP_START_ADDR; 213 | __set_MSP(msp_value); 214 | 215 | // Set up reset handler function pointer 216 | uint32_t resethandler_address = *(__IO uint32_t *) (APP_START_ADDR + 4); 217 | app_reset_handler = (void*) resethandler_address; 218 | 219 | // Call app reset handler to jump to app code 220 | app_reset_handler(); 221 | 222 | } 223 | 224 | bool bootloader_requested(){ 225 | // If DIP_3 is ON, skip boot bits check and run bootloader 226 | if(!HAL_GPIO_ReadPin(DIP_3_GPIO_Port, DIP_3_Pin)){ 227 | return true; 228 | } 229 | 230 | // If boot bits are set for bootloader (BTL), run bootloader 231 | // if they aren't set, run app 232 | if(boot_bits[0] == 'B' && boot_bits[1] == 'T' && boot_bits[2] == 'L'){ 233 | return true; 234 | } else { 235 | return false; 236 | } 237 | } 238 | 239 | void bootloader_init(){ 240 | if(bootloader_requested()){ 241 | // Continue 242 | }else{ 243 | bootloader_jump_to_user_app(); 244 | } 245 | 246 | __enable_irq(); 247 | init_and_start_can(); 248 | } 249 | 250 | void bootloader_loop(){ 251 | if(flashing_firmware){ 252 | HAL_GPIO_WritePin(LED_B_GPIO_Port, LED_B_Pin, 0); 253 | HAL_Delay(100); 254 | HAL_GPIO_WritePin(LED_B_GPIO_Port, LED_B_Pin, 1); 255 | HAL_Delay(200); 256 | } else { 257 | HAL_GPIO_WritePin(LED_B_GPIO_Port, LED_B_Pin, 0); 258 | HAL_Delay(100); 259 | HAL_GPIO_WritePin(LED_B_GPIO_Port, LED_B_Pin, 1); 260 | HAL_Delay(900); 261 | } 262 | 263 | } 264 | 265 | void erase_flash(){ 266 | 267 | HAL_FLASH_Unlock(); 268 | __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR); // Not quite sure this was included in example code 269 | 270 | // Set up erase pages 271 | FirstPage = GetPage(APP_START_ADDR); 272 | NbOfPages = GetPage(APP_END_ADDR) - FirstPage + 1; 273 | // Set up erase struct 274 | EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; 275 | EraseInitStruct.Page = FirstPage; 276 | EraseInitStruct.NbPages = NbOfPages; 277 | 278 | // Perform erase 279 | if(HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK){ 280 | Error_Handler(); 281 | } 282 | 283 | HAL_FLASH_Lock(); 284 | } -------------------------------------------------------------------------------- /bootloader/Core/Src/can.c: -------------------------------------------------------------------------------- 1 | #include "can.h" 2 | 3 | FDCAN_TxHeaderTypeDef TxHeader; 4 | FDCAN_RxHeaderTypeDef RxHeader; 5 | uint8_t TxData[8]; 6 | uint8_t RxData[8]; 7 | 8 | enum canBitrate can_bitrate = _500Kbs; 9 | 10 | void init_and_start_can() 11 | { 12 | // Set up CAN header 13 | TxHeader.Identifier = 0; 14 | TxHeader.IdType = FDCAN_STANDARD_ID; 15 | TxHeader.TxFrameType = FDCAN_DATA_FRAME; 16 | TxHeader.DataLength = FDCAN_DLC_BYTES_8; 17 | TxHeader.BitRateSwitch = FDCAN_BRS_OFF; 18 | TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS; 19 | TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; 20 | TxHeader.FDFormat = FDCAN_CLASSIC_CAN; 21 | 22 | // TODO: Filter doesn't seem to be working yet 23 | FDCAN_FilterTypeDef sFilterConfig; 24 | 25 | sFilterConfig.IdType = FDCAN_STANDARD_ID; 26 | sFilterConfig.FilterIndex = 1; 27 | sFilterConfig.FilterType = FDCAN_FILTER_RANGE; 28 | sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; 29 | sFilterConfig.FilterID1 = 0x00; 30 | sFilterConfig.FilterID2 = 0x01; 31 | 32 | if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK) 33 | { 34 | /* Filter configuration Error */ 35 | Error_Handler(); 36 | } 37 | 38 | can_set_500kbs(); 39 | 40 | if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK) 41 | { 42 | Error_Handler(); 43 | } 44 | 45 | if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK) 46 | { 47 | Error_Handler(); 48 | } 49 | 50 | // Activate the notification for new data in FIFO0 for FDCAN1 51 | if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK) 52 | { 53 | /* Notification Error */ 54 | Error_Handler(); 55 | } 56 | } 57 | 58 | 59 | // Set registers for 500_000 kb/s timing 60 | void can_set_500kbs() 61 | { 62 | hfdcan1.Init.NominalPrescaler = 16; 63 | hfdcan1.Init.NominalTimeSeg1 = 15; 64 | hfdcan1.Init.NominalTimeSeg2 = 2; 65 | can_bitrate = _500Kbs; 66 | } 67 | 68 | // Set registers for 1_000_000 kb/s (1Mbit) timing 69 | void can_set_1000kbs() 70 | { 71 | hfdcan1.Init.NominalPrescaler = 8; 72 | hfdcan1.Init.NominalTimeSeg1 = 15; 73 | hfdcan1.Init.NominalTimeSeg2 = 2; 74 | can_bitrate = _1000Kbs; 75 | } 76 | 77 | void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) 78 | { 79 | if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET) 80 | { 81 | /* Retreive Rx messages from RX FIFO0 */ 82 | if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK) 83 | { 84 | /* Reception Error */ 85 | Error_Handler(); 86 | } 87 | 88 | process_CAN_rx(&RxHeader, RxData); 89 | } 90 | } -------------------------------------------------------------------------------- /bootloader/Core/Src/main.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : main.c 5 | * @brief : Main program body 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2023 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file 13 | * in the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | * 16 | ****************************************************************************** 17 | */ 18 | /* USER CODE END Header */ 19 | /* Includes ------------------------------------------------------------------*/ 20 | #include "main.h" 21 | #include "usb_device.h" 22 | 23 | /* Private includes ----------------------------------------------------------*/ 24 | /* USER CODE BEGIN Includes */ 25 | #include "bootloader.h" 26 | /* USER CODE END Includes */ 27 | 28 | /* Private typedef -----------------------------------------------------------*/ 29 | /* USER CODE BEGIN PTD */ 30 | 31 | /* USER CODE END PTD */ 32 | 33 | /* Private define ------------------------------------------------------------*/ 34 | /* USER CODE BEGIN PD */ 35 | 36 | /* USER CODE END PD */ 37 | 38 | /* Private macro -------------------------------------------------------------*/ 39 | /* USER CODE BEGIN PM */ 40 | 41 | /* USER CODE END PM */ 42 | 43 | /* Private variables ---------------------------------------------------------*/ 44 | FDCAN_HandleTypeDef hfdcan1; 45 | 46 | /* USER CODE BEGIN PV */ 47 | 48 | /* USER CODE END PV */ 49 | 50 | /* Private function prototypes -----------------------------------------------*/ 51 | void SystemClock_Config(void); 52 | static void MX_GPIO_Init(void); 53 | static void MX_FDCAN1_Init(void); 54 | /* USER CODE BEGIN PFP */ 55 | 56 | /* USER CODE END PFP */ 57 | 58 | /* Private user code ---------------------------------------------------------*/ 59 | /* USER CODE BEGIN 0 */ 60 | 61 | /* USER CODE END 0 */ 62 | 63 | /** 64 | * @brief The application entry point. 65 | * @retval int 66 | */ 67 | int main(void) 68 | { 69 | /* USER CODE BEGIN 1 */ 70 | 71 | /* USER CODE END 1 */ 72 | 73 | /* MCU Configuration--------------------------------------------------------*/ 74 | 75 | /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ 76 | HAL_Init(); 77 | 78 | /* USER CODE BEGIN Init */ 79 | 80 | /* USER CODE END Init */ 81 | 82 | /* Configure the system clock */ 83 | SystemClock_Config(); 84 | 85 | /* USER CODE BEGIN SysInit */ 86 | 87 | /* USER CODE END SysInit */ 88 | 89 | /* Initialize all configured peripherals */ 90 | MX_GPIO_Init(); 91 | MX_FDCAN1_Init(); 92 | MX_USB_Device_Init(); 93 | /* USER CODE BEGIN 2 */ 94 | bootloader_init(); 95 | 96 | HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, 1); 97 | HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, 1); 98 | HAL_GPIO_WritePin(LED_B_GPIO_Port, LED_B_Pin, 1); 99 | /* USER CODE END 2 */ 100 | 101 | /* Infinite loop */ 102 | /* USER CODE BEGIN WHILE */ 103 | while (1) 104 | { 105 | /* USER CODE END WHILE */ 106 | 107 | /* USER CODE BEGIN 3 */ 108 | bootloader_loop(); 109 | } 110 | /* USER CODE END 3 */ 111 | } 112 | 113 | /** 114 | * @brief System Clock Configuration 115 | * @retval None 116 | */ 117 | void SystemClock_Config(void) 118 | { 119 | RCC_OscInitTypeDef RCC_OscInitStruct = {0}; 120 | RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; 121 | 122 | /** Configure the main internal regulator output voltage 123 | */ 124 | HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); 125 | 126 | /** Initializes the RCC Oscillators according to the specified parameters 127 | * in the RCC_OscInitTypeDef structure. 128 | */ 129 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; 130 | RCC_OscInitStruct.HSIState = RCC_HSI_ON; 131 | RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; 132 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 133 | RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; 134 | RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV6; 135 | RCC_OscInitStruct.PLL.PLLN = 108; 136 | RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 137 | RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV6; 138 | RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; 139 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) 140 | { 141 | Error_Handler(); 142 | } 143 | 144 | /** Initializes the CPU, AHB and APB buses clocks 145 | */ 146 | RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK 147 | |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; 148 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 149 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 150 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; 151 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 152 | 153 | if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) 154 | { 155 | Error_Handler(); 156 | } 157 | } 158 | 159 | /** 160 | * @brief FDCAN1 Initialization Function 161 | * @param None 162 | * @retval None 163 | */ 164 | static void MX_FDCAN1_Init(void) 165 | { 166 | 167 | /* USER CODE BEGIN FDCAN1_Init 0 */ 168 | 169 | /* USER CODE END FDCAN1_Init 0 */ 170 | 171 | /* USER CODE BEGIN FDCAN1_Init 1 */ 172 | 173 | /* USER CODE END FDCAN1_Init 1 */ 174 | hfdcan1.Instance = FDCAN1; 175 | hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1; 176 | hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC; 177 | hfdcan1.Init.Mode = FDCAN_MODE_NORMAL; 178 | hfdcan1.Init.AutoRetransmission = DISABLE; 179 | hfdcan1.Init.TransmitPause = ENABLE; 180 | hfdcan1.Init.ProtocolException = DISABLE; 181 | hfdcan1.Init.NominalPrescaler = 16; 182 | hfdcan1.Init.NominalSyncJumpWidth = 1; 183 | hfdcan1.Init.NominalTimeSeg1 = 15; 184 | hfdcan1.Init.NominalTimeSeg2 = 2; 185 | hfdcan1.Init.DataPrescaler = 1; 186 | hfdcan1.Init.DataSyncJumpWidth = 1; 187 | hfdcan1.Init.DataTimeSeg1 = 1; 188 | hfdcan1.Init.DataTimeSeg2 = 1; 189 | hfdcan1.Init.StdFiltersNbr = 0; 190 | hfdcan1.Init.ExtFiltersNbr = 0; 191 | hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; 192 | if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK) 193 | { 194 | Error_Handler(); 195 | } 196 | /* USER CODE BEGIN FDCAN1_Init 2 */ 197 | 198 | /* USER CODE END FDCAN1_Init 2 */ 199 | 200 | } 201 | 202 | /** 203 | * @brief GPIO Initialization Function 204 | * @param None 205 | * @retval None 206 | */ 207 | static void MX_GPIO_Init(void) 208 | { 209 | GPIO_InitTypeDef GPIO_InitStruct = {0}; 210 | /* USER CODE BEGIN MX_GPIO_Init_1 */ 211 | /* USER CODE END MX_GPIO_Init_1 */ 212 | 213 | /* GPIO Ports Clock Enable */ 214 | __HAL_RCC_GPIOC_CLK_ENABLE(); 215 | __HAL_RCC_GPIOA_CLK_ENABLE(); 216 | __HAL_RCC_GPIOB_CLK_ENABLE(); 217 | 218 | /*Configure GPIO pin Output Level */ 219 | HAL_GPIO_WritePin(GPIOA, LED_R_Pin|LED_G_Pin|LED_B_Pin, GPIO_PIN_RESET); 220 | 221 | /*Configure GPIO pin : DIP_3_Pin */ 222 | GPIO_InitStruct.Pin = DIP_3_Pin; 223 | GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 224 | GPIO_InitStruct.Pull = GPIO_PULLUP; 225 | HAL_GPIO_Init(DIP_3_GPIO_Port, &GPIO_InitStruct); 226 | 227 | /*Configure GPIO pins : LED_R_Pin LED_G_Pin LED_B_Pin */ 228 | GPIO_InitStruct.Pin = LED_R_Pin|LED_G_Pin|LED_B_Pin; 229 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 230 | GPIO_InitStruct.Pull = GPIO_NOPULL; 231 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 232 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 233 | 234 | /* USER CODE BEGIN MX_GPIO_Init_2 */ 235 | /* USER CODE END MX_GPIO_Init_2 */ 236 | } 237 | 238 | /* USER CODE BEGIN 4 */ 239 | 240 | /* USER CODE END 4 */ 241 | 242 | /** 243 | * @brief Period elapsed callback in non blocking mode 244 | * @note This function is called when TIM2 interrupt took place, inside 245 | * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment 246 | * a global variable "uwTick" used as application time base. 247 | * @param htim : TIM handle 248 | * @retval None 249 | */ 250 | void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 251 | { 252 | /* USER CODE BEGIN Callback 0 */ 253 | 254 | /* USER CODE END Callback 0 */ 255 | if (htim->Instance == TIM2) { 256 | HAL_IncTick(); 257 | } 258 | /* USER CODE BEGIN Callback 1 */ 259 | 260 | /* USER CODE END Callback 1 */ 261 | } 262 | 263 | /** 264 | * @brief This function is executed in case of error occurrence. 265 | * @retval None 266 | */ 267 | void Error_Handler(void) 268 | { 269 | /* USER CODE BEGIN Error_Handler_Debug */ 270 | /* User can add his own implementation to report the HAL error return state */ 271 | __disable_irq(); 272 | while (1) 273 | { 274 | } 275 | /* USER CODE END Error_Handler_Debug */ 276 | } 277 | 278 | #ifdef USE_FULL_ASSERT 279 | /** 280 | * @brief Reports the name of the source file and the source line number 281 | * where the assert_param error has occurred. 282 | * @param file: pointer to the source file name 283 | * @param line: assert_param error line source number 284 | * @retval None 285 | */ 286 | void assert_failed(uint8_t *file, uint32_t line) 287 | { 288 | /* USER CODE BEGIN 6 */ 289 | /* User can add his own implementation to report the file name and line number, 290 | ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ 291 | /* USER CODE END 6 */ 292 | } 293 | #endif /* USE_FULL_ASSERT */ 294 | -------------------------------------------------------------------------------- /bootloader/Core/Src/stm32g4xx_hal_msp.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file stm32g4xx_hal_msp.c 5 | * @brief This file provides code for the MSP Initialization 6 | * and de-Initialization codes. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Includes ------------------------------------------------------------------*/ 22 | #include "main.h" 23 | 24 | /* USER CODE BEGIN Includes */ 25 | 26 | /* USER CODE END Includes */ 27 | 28 | /* Private typedef -----------------------------------------------------------*/ 29 | /* USER CODE BEGIN TD */ 30 | 31 | /* USER CODE END TD */ 32 | 33 | /* Private define ------------------------------------------------------------*/ 34 | /* USER CODE BEGIN Define */ 35 | 36 | /* USER CODE END Define */ 37 | 38 | /* Private macro -------------------------------------------------------------*/ 39 | /* USER CODE BEGIN Macro */ 40 | 41 | /* USER CODE END Macro */ 42 | 43 | /* Private variables ---------------------------------------------------------*/ 44 | /* USER CODE BEGIN PV */ 45 | 46 | /* USER CODE END PV */ 47 | 48 | /* Private function prototypes -----------------------------------------------*/ 49 | /* USER CODE BEGIN PFP */ 50 | 51 | /* USER CODE END PFP */ 52 | 53 | /* External functions --------------------------------------------------------*/ 54 | /* USER CODE BEGIN ExternalFunctions */ 55 | 56 | /* USER CODE END ExternalFunctions */ 57 | 58 | /* USER CODE BEGIN 0 */ 59 | 60 | /* USER CODE END 0 */ 61 | /** 62 | * Initializes the Global MSP. 63 | */ 64 | void HAL_MspInit(void) 65 | { 66 | /* USER CODE BEGIN MspInit 0 */ 67 | 68 | /* USER CODE END MspInit 0 */ 69 | 70 | __HAL_RCC_SYSCFG_CLK_ENABLE(); 71 | __HAL_RCC_PWR_CLK_ENABLE(); 72 | 73 | /* System interrupt init*/ 74 | 75 | /** Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral 76 | */ 77 | HAL_PWREx_DisableUCPDDeadBattery(); 78 | 79 | /* USER CODE BEGIN MspInit 1 */ 80 | 81 | /* USER CODE END MspInit 1 */ 82 | } 83 | 84 | /** 85 | * @brief FDCAN MSP Initialization 86 | * This function configures the hardware resources used in this example 87 | * @param hfdcan: FDCAN handle pointer 88 | * @retval None 89 | */ 90 | void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan) 91 | { 92 | GPIO_InitTypeDef GPIO_InitStruct = {0}; 93 | RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; 94 | if(hfdcan->Instance==FDCAN1) 95 | { 96 | /* USER CODE BEGIN FDCAN1_MspInit 0 */ 97 | 98 | /* USER CODE END FDCAN1_MspInit 0 */ 99 | 100 | /** Initializes the peripherals clocks 101 | */ 102 | PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN; 103 | PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1; 104 | if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) 105 | { 106 | Error_Handler(); 107 | } 108 | 109 | /* Peripheral clock enable */ 110 | __HAL_RCC_FDCAN_CLK_ENABLE(); 111 | 112 | __HAL_RCC_GPIOB_CLK_ENABLE(); 113 | /**FDCAN1 GPIO Configuration 114 | PB8-BOOT0 ------> FDCAN1_RX 115 | PB9 ------> FDCAN1_TX 116 | */ 117 | GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; 118 | GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 119 | GPIO_InitStruct.Pull = GPIO_NOPULL; 120 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 121 | GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1; 122 | HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 123 | 124 | /* FDCAN1 interrupt Init */ 125 | HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 0, 0); 126 | HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn); 127 | /* USER CODE BEGIN FDCAN1_MspInit 1 */ 128 | 129 | /* USER CODE END FDCAN1_MspInit 1 */ 130 | } 131 | 132 | } 133 | 134 | /** 135 | * @brief FDCAN MSP De-Initialization 136 | * This function freeze the hardware resources used in this example 137 | * @param hfdcan: FDCAN handle pointer 138 | * @retval None 139 | */ 140 | void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* hfdcan) 141 | { 142 | if(hfdcan->Instance==FDCAN1) 143 | { 144 | /* USER CODE BEGIN FDCAN1_MspDeInit 0 */ 145 | 146 | /* USER CODE END FDCAN1_MspDeInit 0 */ 147 | /* Peripheral clock disable */ 148 | __HAL_RCC_FDCAN_CLK_DISABLE(); 149 | 150 | /**FDCAN1 GPIO Configuration 151 | PB8-BOOT0 ------> FDCAN1_RX 152 | PB9 ------> FDCAN1_TX 153 | */ 154 | HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9); 155 | 156 | /* FDCAN1 interrupt DeInit */ 157 | HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn); 158 | /* USER CODE BEGIN FDCAN1_MspDeInit 1 */ 159 | 160 | /* USER CODE END FDCAN1_MspDeInit 1 */ 161 | } 162 | 163 | } 164 | 165 | /* USER CODE BEGIN 1 */ 166 | 167 | /* USER CODE END 1 */ 168 | -------------------------------------------------------------------------------- /bootloader/Core/Src/stm32g4xx_hal_timebase_tim.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file stm32g4xx_hal_timebase_tim.c 5 | * @brief HAL time base based on the hardware TIM. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2024 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file 13 | * in the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | * 16 | ****************************************************************************** 17 | */ 18 | /* USER CODE END Header */ 19 | 20 | /* Includes ------------------------------------------------------------------*/ 21 | #include "stm32g4xx_hal.h" 22 | #include "stm32g4xx_hal_tim.h" 23 | 24 | /* Private typedef -----------------------------------------------------------*/ 25 | /* Private define ------------------------------------------------------------*/ 26 | /* Private macro -------------------------------------------------------------*/ 27 | /* Private variables ---------------------------------------------------------*/ 28 | TIM_HandleTypeDef htim2; 29 | /* Private function prototypes -----------------------------------------------*/ 30 | /* Private functions ---------------------------------------------------------*/ 31 | 32 | /** 33 | * @brief This function configures the TIM2 as a time base source. 34 | * The time source is configured to have 1ms time base with a dedicated 35 | * Tick interrupt priority. 36 | * @note This function is called automatically at the beginning of program after 37 | * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig(). 38 | * @param TickPriority: Tick interrupt priority. 39 | * @retval HAL status 40 | */ 41 | HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) 42 | { 43 | RCC_ClkInitTypeDef clkconfig; 44 | uint32_t uwTimclock = 0; 45 | uint32_t uwPrescalerValue = 0; 46 | uint32_t pFLatency; 47 | HAL_StatusTypeDef status; 48 | 49 | /* Enable TIM2 clock */ 50 | __HAL_RCC_TIM2_CLK_ENABLE(); 51 | 52 | /* Get clock configuration */ 53 | HAL_RCC_GetClockConfig(&clkconfig, &pFLatency); 54 | 55 | /* Compute TIM2 clock */ 56 | uwTimclock = HAL_RCC_GetPCLK1Freq(); 57 | 58 | /* Compute the prescaler value to have TIM2 counter clock equal to 1MHz */ 59 | uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U); 60 | 61 | /* Initialize TIM2 */ 62 | htim2.Instance = TIM2; 63 | 64 | /* Initialize TIMx peripheral as follow: 65 | 66 | + Period = [(TIM2CLK/1000) - 1]. to have a (1/1000) s time base. 67 | + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock. 68 | + ClockDivision = 0 69 | + Counter direction = Up 70 | */ 71 | htim2.Init.Period = (1000000U / 1000U) - 1U; 72 | htim2.Init.Prescaler = uwPrescalerValue; 73 | htim2.Init.ClockDivision = 0; 74 | htim2.Init.CounterMode = TIM_COUNTERMODE_UP; 75 | 76 | status = HAL_TIM_Base_Init(&htim2); 77 | if (status == HAL_OK) 78 | { 79 | /* Start the TIM time Base generation in interrupt mode */ 80 | status = HAL_TIM_Base_Start_IT(&htim2); 81 | if (status == HAL_OK) 82 | { 83 | /* Enable the TIM2 global Interrupt */ 84 | HAL_NVIC_EnableIRQ(TIM2_IRQn); 85 | /* Configure the SysTick IRQ priority */ 86 | if (TickPriority < (1UL << __NVIC_PRIO_BITS)) 87 | { 88 | /* Configure the TIM IRQ priority */ 89 | HAL_NVIC_SetPriority(TIM2_IRQn, TickPriority, 0U); 90 | uwTickPrio = TickPriority; 91 | } 92 | else 93 | { 94 | status = HAL_ERROR; 95 | } 96 | } 97 | } 98 | 99 | /* Return function status */ 100 | return status; 101 | } 102 | 103 | /** 104 | * @brief Suspend Tick increment. 105 | * @note Disable the tick increment by disabling TIM2 update interrupt. 106 | * @param None 107 | * @retval None 108 | */ 109 | void HAL_SuspendTick(void) 110 | { 111 | /* Disable TIM2 update Interrupt */ 112 | __HAL_TIM_DISABLE_IT(&htim2, TIM_IT_UPDATE); 113 | } 114 | 115 | /** 116 | * @brief Resume Tick increment. 117 | * @note Enable the tick increment by Enabling TIM2 update interrupt. 118 | * @param None 119 | * @retval None 120 | */ 121 | void HAL_ResumeTick(void) 122 | { 123 | /* Enable TIM2 Update interrupt */ 124 | __HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE); 125 | } 126 | 127 | -------------------------------------------------------------------------------- /bootloader/Core/Src/stm32g4xx_it.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file stm32g4xx_it.c 5 | * @brief Interrupt Service Routines. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2023 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file 13 | * in the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | * 16 | ****************************************************************************** 17 | */ 18 | /* USER CODE END Header */ 19 | 20 | /* Includes ------------------------------------------------------------------*/ 21 | #include "main.h" 22 | #include "stm32g4xx_it.h" 23 | /* Private includes ----------------------------------------------------------*/ 24 | /* USER CODE BEGIN Includes */ 25 | /* USER CODE END Includes */ 26 | 27 | /* Private typedef -----------------------------------------------------------*/ 28 | /* USER CODE BEGIN TD */ 29 | 30 | /* USER CODE END TD */ 31 | 32 | /* Private define ------------------------------------------------------------*/ 33 | /* USER CODE BEGIN PD */ 34 | 35 | /* USER CODE END PD */ 36 | 37 | /* Private macro -------------------------------------------------------------*/ 38 | /* USER CODE BEGIN PM */ 39 | 40 | /* USER CODE END PM */ 41 | 42 | /* Private variables ---------------------------------------------------------*/ 43 | /* USER CODE BEGIN PV */ 44 | 45 | /* USER CODE END PV */ 46 | 47 | /* Private function prototypes -----------------------------------------------*/ 48 | /* USER CODE BEGIN PFP */ 49 | 50 | /* USER CODE END PFP */ 51 | 52 | /* Private user code ---------------------------------------------------------*/ 53 | /* USER CODE BEGIN 0 */ 54 | 55 | /* USER CODE END 0 */ 56 | 57 | /* External variables --------------------------------------------------------*/ 58 | extern PCD_HandleTypeDef hpcd_USB_FS; 59 | extern FDCAN_HandleTypeDef hfdcan1; 60 | extern TIM_HandleTypeDef htim2; 61 | 62 | /* USER CODE BEGIN EV */ 63 | 64 | /* USER CODE END EV */ 65 | 66 | /******************************************************************************/ 67 | /* Cortex-M4 Processor Interruption and Exception Handlers */ 68 | /******************************************************************************/ 69 | /** 70 | * @brief This function handles Non maskable interrupt. 71 | */ 72 | void NMI_Handler(void) 73 | { 74 | /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ 75 | 76 | /* USER CODE END NonMaskableInt_IRQn 0 */ 77 | /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ 78 | while (1) 79 | { 80 | } 81 | /* USER CODE END NonMaskableInt_IRQn 1 */ 82 | } 83 | 84 | /** 85 | * @brief This function handles Hard fault interrupt. 86 | */ 87 | void HardFault_Handler(void) 88 | { 89 | /* USER CODE BEGIN HardFault_IRQn 0 */ 90 | 91 | /* USER CODE END HardFault_IRQn 0 */ 92 | while (1) 93 | { 94 | /* USER CODE BEGIN W1_HardFault_IRQn 0 */ 95 | /* USER CODE END W1_HardFault_IRQn 0 */ 96 | } 97 | } 98 | 99 | /** 100 | * @brief This function handles Memory management fault. 101 | */ 102 | void MemManage_Handler(void) 103 | { 104 | /* USER CODE BEGIN MemoryManagement_IRQn 0 */ 105 | 106 | /* USER CODE END MemoryManagement_IRQn 0 */ 107 | while (1) 108 | { 109 | /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ 110 | /* USER CODE END W1_MemoryManagement_IRQn 0 */ 111 | } 112 | } 113 | 114 | /** 115 | * @brief This function handles Prefetch fault, memory access fault. 116 | */ 117 | void BusFault_Handler(void) 118 | { 119 | /* USER CODE BEGIN BusFault_IRQn 0 */ 120 | 121 | /* USER CODE END BusFault_IRQn 0 */ 122 | while (1) 123 | { 124 | /* USER CODE BEGIN W1_BusFault_IRQn 0 */ 125 | /* USER CODE END W1_BusFault_IRQn 0 */ 126 | } 127 | } 128 | 129 | /** 130 | * @brief This function handles Undefined instruction or illegal state. 131 | */ 132 | void UsageFault_Handler(void) 133 | { 134 | /* USER CODE BEGIN UsageFault_IRQn 0 */ 135 | 136 | /* USER CODE END UsageFault_IRQn 0 */ 137 | while (1) 138 | { 139 | /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ 140 | /* USER CODE END W1_UsageFault_IRQn 0 */ 141 | } 142 | } 143 | 144 | /** 145 | * @brief This function handles System service call via SWI instruction. 146 | */ 147 | void SVC_Handler(void) 148 | { 149 | /* USER CODE BEGIN SVCall_IRQn 0 */ 150 | 151 | /* USER CODE END SVCall_IRQn 0 */ 152 | /* USER CODE BEGIN SVCall_IRQn 1 */ 153 | 154 | /* USER CODE END SVCall_IRQn 1 */ 155 | } 156 | 157 | /** 158 | * @brief This function handles Debug monitor. 159 | */ 160 | void DebugMon_Handler(void) 161 | { 162 | /* USER CODE BEGIN DebugMonitor_IRQn 0 */ 163 | 164 | /* USER CODE END DebugMonitor_IRQn 0 */ 165 | /* USER CODE BEGIN DebugMonitor_IRQn 1 */ 166 | 167 | /* USER CODE END DebugMonitor_IRQn 1 */ 168 | } 169 | 170 | /** 171 | * @brief This function handles Pendable request for system service. 172 | */ 173 | void PendSV_Handler(void) 174 | { 175 | /* USER CODE BEGIN PendSV_IRQn 0 */ 176 | 177 | /* USER CODE END PendSV_IRQn 0 */ 178 | /* USER CODE BEGIN PendSV_IRQn 1 */ 179 | 180 | /* USER CODE END PendSV_IRQn 1 */ 181 | } 182 | 183 | /** 184 | * @brief This function handles System tick timer. 185 | */ 186 | void SysTick_Handler(void) 187 | { 188 | /* USER CODE BEGIN SysTick_IRQn 0 */ 189 | 190 | /* USER CODE END SysTick_IRQn 0 */ 191 | 192 | /* USER CODE BEGIN SysTick_IRQn 1 */ 193 | 194 | /* USER CODE END SysTick_IRQn 1 */ 195 | } 196 | 197 | /******************************************************************************/ 198 | /* STM32G4xx Peripheral Interrupt Handlers */ 199 | /* Add here the Interrupt Handlers for the used peripherals. */ 200 | /* For the available peripheral interrupt handler names, */ 201 | /* please refer to the startup file (startup_stm32g4xx.s). */ 202 | /******************************************************************************/ 203 | 204 | /** 205 | * @brief This function handles USB low priority interrupt remap. 206 | */ 207 | void USB_LP_IRQHandler(void) 208 | { 209 | /* USER CODE BEGIN USB_LP_IRQn 0 */ 210 | 211 | /* USER CODE END USB_LP_IRQn 0 */ 212 | HAL_PCD_IRQHandler(&hpcd_USB_FS); 213 | /* USER CODE BEGIN USB_LP_IRQn 1 */ 214 | 215 | /* USER CODE END USB_LP_IRQn 1 */ 216 | } 217 | 218 | /** 219 | * @brief This function handles FDCAN1 interrupt 0. 220 | */ 221 | void FDCAN1_IT0_IRQHandler(void) 222 | { 223 | /* USER CODE BEGIN FDCAN1_IT0_IRQn 0 */ 224 | 225 | /* USER CODE END FDCAN1_IT0_IRQn 0 */ 226 | HAL_FDCAN_IRQHandler(&hfdcan1); 227 | /* USER CODE BEGIN FDCAN1_IT0_IRQn 1 */ 228 | 229 | /* USER CODE END FDCAN1_IT0_IRQn 1 */ 230 | } 231 | 232 | /** 233 | * @brief This function handles TIM2 global interrupt. 234 | */ 235 | void TIM2_IRQHandler(void) 236 | { 237 | /* USER CODE BEGIN TIM2_IRQn 0 */ 238 | 239 | /* USER CODE END TIM2_IRQn 0 */ 240 | HAL_TIM_IRQHandler(&htim2); 241 | /* USER CODE BEGIN TIM2_IRQn 1 */ 242 | 243 | /* USER CODE END TIM2_IRQn 1 */ 244 | } 245 | 246 | /* USER CODE BEGIN 1 */ 247 | 248 | /* USER CODE END 1 */ 249 | -------------------------------------------------------------------------------- /bootloader/Makefile: -------------------------------------------------------------------------------- 1 | ########################################################################################################################## 2 | # File automatically-generated by tool: [projectgenerator] version: [4.1.0] date: [Mon Jan 01 09:32:58 PST 2024] 3 | ########################################################################################################################## 4 | 5 | # ------------------------------------------------ 6 | # Generic Makefile (based on gcc) 7 | # 8 | # ChangeLog : 9 | # 2017-02-10 - Several enhancements + project update mode 10 | # 2015-07-22 - first version 11 | # ------------------------------------------------ 12 | 13 | ###################################### 14 | # target 15 | ###################################### 16 | TARGET = 50x50_Bootloader 17 | 18 | 19 | ###################################### 20 | # building variables 21 | ###################################### 22 | # debug build? 23 | DEBUG = 1 24 | # optimization 25 | OPT = -Og 26 | 27 | 28 | ####################################### 29 | # paths 30 | ####################################### 31 | # Build path 32 | BUILD_DIR = build 33 | 34 | ###################################### 35 | # source 36 | ###################################### 37 | # C sources 38 | C_SOURCES = \ 39 | Core/Src/main.c \ 40 | Core/Src/stm32g4xx_it.c \ 41 | Core/Src/stm32g4xx_hal_msp.c \ 42 | USB_Device/App/usb_device.c \ 43 | USB_Device/App/usbd_desc.c \ 44 | USB_Device/App/usbd_cdc_if.c \ 45 | USB_Device/Target/usbd_conf.c \ 46 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pcd.c \ 47 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pcd_ex.c \ 48 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_ll_usb.c \ 49 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal.c \ 50 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_rcc.c \ 51 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_rcc_ex.c \ 52 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash.c \ 53 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash_ex.c \ 54 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash_ramfunc.c \ 55 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_gpio.c \ 56 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_exti.c \ 57 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_dma.c \ 58 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_dma_ex.c \ 59 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr.c \ 60 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr_ex.c \ 61 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_cortex.c \ 62 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_fdcan.c \ 63 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_tim.c \ 64 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_tim_ex.c \ 65 | Core/Src/system_stm32g4xx.c \ 66 | Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c \ 67 | Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c \ 68 | Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c \ 69 | Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c \ 70 | Core/Src/stm32g4xx_hal_timebase_tim.c 71 | 72 | # ASM sources 73 | ASM_SOURCES = \ 74 | startup_stm32g431xx.s 75 | 76 | 77 | ####################################### 78 | # binaries 79 | ####################################### 80 | PREFIX = arm-none-eabi- 81 | # The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx) 82 | # either it can be added to the PATH environment variable. 83 | ifdef GCC_PATH 84 | CC = $(GCC_PATH)/$(PREFIX)gcc 85 | AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp 86 | CP = $(GCC_PATH)/$(PREFIX)objcopy 87 | SZ = $(GCC_PATH)/$(PREFIX)size 88 | else 89 | CC = $(PREFIX)gcc 90 | AS = $(PREFIX)gcc -x assembler-with-cpp 91 | CP = $(PREFIX)objcopy 92 | SZ = $(PREFIX)size 93 | endif 94 | HEX = $(CP) -O ihex 95 | BIN = $(CP) -O binary -S 96 | 97 | ####################################### 98 | # CFLAGS 99 | ####################################### 100 | # cpu 101 | CPU = -mcpu=cortex-m4 102 | 103 | # fpu 104 | FPU = -mfpu=fpv4-sp-d16 105 | 106 | # float-abi 107 | FLOAT-ABI = -mfloat-abi=hard 108 | 109 | # mcu 110 | MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI) 111 | 112 | # macros for gcc 113 | # AS defines 114 | AS_DEFS = 115 | 116 | # C defines 117 | C_DEFS = \ 118 | -DUSE_HAL_DRIVER \ 119 | -DSTM32G431xx 120 | 121 | 122 | # AS includes 123 | AS_INCLUDES = 124 | 125 | # C includes 126 | C_INCLUDES = \ 127 | -IUSB_Device/App \ 128 | -IUSB_Device/Target \ 129 | -ICore/Inc \ 130 | -IDrivers/STM32G4xx_HAL_Driver/Inc \ 131 | -IDrivers/STM32G4xx_HAL_Driver/Inc/Legacy \ 132 | -IMiddlewares/ST/STM32_USB_Device_Library/Core/Inc \ 133 | -IMiddlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc \ 134 | -IDrivers/CMSIS/Device/ST/STM32G4xx/Include \ 135 | -IDrivers/CMSIS/Include 136 | 137 | 138 | # compile gcc flags 139 | ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections 140 | 141 | CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections 142 | 143 | ifeq ($(DEBUG), 1) 144 | CFLAGS += -g -gdwarf-2 145 | endif 146 | 147 | 148 | # Generate dependency information 149 | CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" 150 | 151 | 152 | ####################################### 153 | # LDFLAGS 154 | ####################################### 155 | # link script 156 | LDSCRIPT = STM32G431CBUx_FLASH.ld 157 | 158 | # libraries 159 | LIBS = -lc -lm -lnosys 160 | LIBDIR = 161 | LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections 162 | 163 | # default action: build all 164 | all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin 165 | 166 | 167 | ####################################### 168 | # build the application 169 | ####################################### 170 | # list of objects 171 | OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o))) 172 | vpath %.c $(sort $(dir $(C_SOURCES))) 173 | # list of ASM program objects 174 | OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o))) 175 | vpath %.s $(sort $(dir $(ASM_SOURCES))) 176 | 177 | $(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) 178 | $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@ 179 | 180 | $(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR) 181 | $(AS) -c $(CFLAGS) $< -o $@ 182 | 183 | $(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile 184 | $(CC) $(OBJECTS) $(LDFLAGS) -o $@ 185 | $(SZ) $@ 186 | 187 | $(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR) 188 | $(HEX) $< $@ 189 | 190 | $(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR) 191 | $(BIN) $< $@ 192 | 193 | $(BUILD_DIR): 194 | mkdir $@ 195 | 196 | ####################################### 197 | # clean up 198 | ####################################### 199 | clean: 200 | -rm -fR $(BUILD_DIR) 201 | 202 | ####################################### 203 | # dependencies 204 | ####################################### 205 | -include $(wildcard $(BUILD_DIR)/*.d) 206 | 207 | # *** EOF *** 208 | -------------------------------------------------------------------------------- /bootloader/STM32-for-VSCode.config.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for the STM32 for VSCode extension 2 | # Arrays can be inputted in two ways. One is: [entry_1, entry_2, ..., entry_final] 3 | # or by adding an indented list below the variable name e.g.: 4 | # VARIABLE: 5 | # - entry_1 6 | # - entry_2 7 | 8 | # The project name 9 | target: 50x50_Bootloader 10 | # Can be C or C++ 11 | language: C 12 | 13 | optimization: Og 14 | 15 | # MCU settings 16 | targetMCU: stm32g4x 17 | cpu: cortex-m4 # type of cpu e.g. cortex-m4 18 | fpu: fpv4-sp-d16 # Defines how floating points are defined. Can be left empty. 19 | floatAbi: -mfloat-abi=hard 20 | ldscript: STM32G431CBUx_FLASH.ld # linker script 21 | 22 | # Compiler definitions. The -D prefix for the compiler will be automatically added. 23 | cDefinitions: [] 24 | cxxDefinitions: [] 25 | asDefinitions: [] 26 | 27 | # Compiler definition files. you can add a single files or an array of files for different definitions. 28 | # The file is expected to have a definition each new line. 29 | # This allows to include for example a .definition file which can be ignored in git and can contain 30 | # This can be convenient for passing along secrets at compile time, or generating a file for per device setup. 31 | cDefinitionsFile: 32 | cxxDefinitionsFile: 33 | asDefinitionsFile: 34 | 35 | # Compiler flags 36 | cFlags: 37 | - -Wall 38 | - -fdata-sections 39 | - -ffunction-sections 40 | 41 | cxxFlags: [] 42 | assemblyFlags: 43 | - -Wall 44 | - -fdata-sections 45 | - -ffunction-sections 46 | 47 | linkerFlags: [] 48 | 49 | # libraries to be included. The -l prefix to the library will be automatically added. 50 | libraries: 51 | - c 52 | - m 53 | 54 | # Library directories. Folders can be added here that contain custom libraries. 55 | libraryDirectories: [] 56 | 57 | # Files or folders that will be excluded from compilation. 58 | # Glob patterns (https://www.wikiwand.com/en/Glob_(programming)) can be used. 59 | # Do mind that double stars are reserved in yaml 60 | # these should be escaped with a: \ or the name should be in double quotes e.g. "**.test.**" 61 | excludes: 62 | - "**/Examples/**" 63 | - "**/examples/**" 64 | - "**/Example/**" 65 | - "**/example/**" 66 | - "**_template.*" 67 | 68 | 69 | # Include directories (directories containing .h or .hpp files) 70 | # If a CubeMX makefile is present it will automatically include the include directories from that makefile. 71 | includeDirectories: 72 | - Inc/** 73 | - Core/Inc/** 74 | - Core/Lib/** 75 | - Src/** 76 | - Core/Src/** 77 | - Core/Lib/** 78 | 79 | 80 | # Files that should be included in the compilation. 81 | # If a CubeMX makefile is present it will automatically include the c and cpp/cxx files from that makefile. 82 | # Glob patterns (https://www.wikiwand.com/en/Glob_(programming)) can be used. 83 | # Do mind that double stars are reserved in yaml 84 | # these should be escaped with a: \ or the name should be in double quotes e.g. "HARDWARE_DRIVER*.c" 85 | sourceFiles: 86 | - Src/** 87 | - Core/Src/** 88 | - Core/Lib/** 89 | 90 | 91 | # When no makefile is present it will show a warning pop-up. 92 | # However when compilation without the CubeMX Makefile is desired, this can be turned of. 93 | suppressMakefileWarning: false 94 | 95 | # Custom makefile rules 96 | # Here custom makefile rules can be added to the STM32Make.make file 97 | # an example of how this can be used is commented out below. 98 | customMakefileRules: 99 | # - command: sayhello 100 | # rule: echo "hello" 101 | # dependsOn: $(BUILD_DIR)/$(TARGET).elf # can be left out 102 | 103 | # Additional flags which will be used when invoking the make command 104 | makeFlags: 105 | # - -O # use this option when the output of make is mixed up only works for make version 4.0 and upwards 106 | # - --silent # use this option to silence the output of the build 107 | -------------------------------------------------------------------------------- /bootloader/STM32G431CBUx_FLASH.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | ** 4 | 5 | ** File : LinkerScript.ld 6 | ** 7 | ** Author : STM32CubeMX 8 | ** 9 | ** Abstract : Linker script for STM32G431CBUx series 10 | ** 128Kbytes FLASH and 32Kbytes RAM 11 | ** 12 | ** Set heap size, stack size and stack location according 13 | ** to application requirements. 14 | ** 15 | ** Set memory bank area and size if external memory is used. 16 | ** 17 | ** Target : STMicroelectronics STM32 18 | ** 19 | ** Distribution: The file is distributed “as is,” without any warranty 20 | ** of any kind. 21 | ** 22 | ***************************************************************************** 23 | ** @attention 24 | ** 25 | **

© COPYRIGHT(c) 2019 STMicroelectronics

26 | ** 27 | ** Redistribution and use in source and binary forms, with or without modification, 28 | ** are permitted provided that the following conditions are met: 29 | ** 1. Redistributions of source code must retain the above copyright notice, 30 | ** this list of conditions and the following disclaimer. 31 | ** 2. Redistributions in binary form must reproduce the above copyright notice, 32 | ** this list of conditions and the following disclaimer in the documentation 33 | ** and/or other materials provided with the distribution. 34 | ** 3. Neither the name of STMicroelectronics nor the names of its contributors 35 | ** may be used to endorse or promote products derived from this software 36 | ** without specific prior written permission. 37 | ** 38 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 39 | ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 41 | ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 42 | ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 43 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 44 | ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 45 | ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 | ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 47 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 48 | ** 49 | ***************************************************************************** 50 | */ 51 | 52 | /* Entry Point */ 53 | ENTRY(Reset_Handler) 54 | 55 | /* Highest address of the user mode stack */ 56 | _estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM */ 57 | /* Generate a link error if heap and stack don't fit into RAM */ 58 | _Min_Heap_Size = 0x200; /* required amount of heap */ 59 | _Min_Stack_Size = 0x400; /* required amount of stack */ 60 | 61 | /* Specify the memory areas */ 62 | MEMORY 63 | { 64 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K 65 | FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 96K 66 | } 67 | 68 | /* Define output sections */ 69 | SECTIONS 70 | { 71 | /* The startup code goes first into FLASH */ 72 | .isr_vector : 73 | { 74 | . = ALIGN(4); 75 | KEEP(*(.isr_vector)) /* Startup code */ 76 | . = ALIGN(4); 77 | } >FLASH 78 | 79 | .bootBlockRAM 0x20000100 (NOLOAD): 80 | { 81 | KEEP(*(.bootBlockRAM)) 82 | } > RAM 83 | 84 | /* The program code and other data goes into FLASH */ 85 | .text : 86 | { 87 | . = ALIGN(4); 88 | *(.text) /* .text sections (code) */ 89 | *(.text*) /* .text* sections (code) */ 90 | *(.glue_7) /* glue arm to thumb code */ 91 | *(.glue_7t) /* glue thumb to arm code */ 92 | *(.eh_frame) 93 | 94 | KEEP (*(.init)) 95 | KEEP (*(.fini)) 96 | 97 | . = ALIGN(4); 98 | _etext = .; /* define a global symbols at end of code */ 99 | } >FLASH 100 | 101 | /* Constant data goes into FLASH */ 102 | .rodata : 103 | { 104 | . = ALIGN(4); 105 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 106 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 107 | . = ALIGN(4); 108 | } >FLASH 109 | 110 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH 111 | .ARM : { 112 | __exidx_start = .; 113 | *(.ARM.exidx*) 114 | __exidx_end = .; 115 | } >FLASH 116 | 117 | .preinit_array : 118 | { 119 | PROVIDE_HIDDEN (__preinit_array_start = .); 120 | KEEP (*(.preinit_array*)) 121 | PROVIDE_HIDDEN (__preinit_array_end = .); 122 | } >FLASH 123 | .init_array : 124 | { 125 | PROVIDE_HIDDEN (__init_array_start = .); 126 | KEEP (*(SORT(.init_array.*))) 127 | KEEP (*(.init_array*)) 128 | PROVIDE_HIDDEN (__init_array_end = .); 129 | } >FLASH 130 | .fini_array : 131 | { 132 | PROVIDE_HIDDEN (__fini_array_start = .); 133 | KEEP (*(SORT(.fini_array.*))) 134 | KEEP (*(.fini_array*)) 135 | PROVIDE_HIDDEN (__fini_array_end = .); 136 | } >FLASH 137 | 138 | /* used by the startup to initialize data */ 139 | _sidata = LOADADDR(.data); 140 | 141 | /* Initialized data sections goes into RAM, load LMA copy after code */ 142 | .data : 143 | { 144 | . = ALIGN(4); 145 | _sdata = .; /* create a global symbol at data start */ 146 | *(.data) /* .data sections */ 147 | *(.data*) /* .data* sections */ 148 | 149 | . = ALIGN(4); 150 | _edata = .; /* define a global symbol at data end */ 151 | } >RAM AT> FLASH 152 | 153 | 154 | /* Uninitialized data section */ 155 | . = ALIGN(4); 156 | .bss : 157 | { 158 | /* This is used by the startup in order to initialize the .bss secion */ 159 | _sbss = .; /* define a global symbol at bss start */ 160 | __bss_start__ = _sbss; 161 | *(.bss) 162 | *(.bss*) 163 | *(COMMON) 164 | 165 | . = ALIGN(4); 166 | _ebss = .; /* define a global symbol at bss end */ 167 | __bss_end__ = _ebss; 168 | } >RAM 169 | 170 | /* User_heap_stack section, used to check that there is enough RAM left */ 171 | ._user_heap_stack : 172 | { 173 | . = ALIGN(8); 174 | PROVIDE ( end = . ); 175 | PROVIDE ( _end = . ); 176 | . = . + _Min_Heap_Size; 177 | . = . + _Min_Stack_Size; 178 | . = ALIGN(8); 179 | } >RAM 180 | 181 | 182 | 183 | /* Remove information from the standard libraries */ 184 | /DISCARD/ : 185 | { 186 | libc.a ( * ) 187 | libm.a ( * ) 188 | libgcc.a ( * ) 189 | } 190 | 191 | .ARM.attributes 0 : { *(.ARM.attributes) } 192 | } 193 | 194 | 195 | -------------------------------------------------------------------------------- /bootloader/STM32Make.make: -------------------------------------------------------------------------------- 1 | ########################################################################################################################## 2 | # File automatically-generated by STM32forVSCode 3 | ########################################################################################################################## 4 | 5 | # ------------------------------------------------ 6 | # Generic Makefile (based on gcc) 7 | # 8 | # ChangeLog : 9 | # 2017-02-10 - Several enhancements + project update mode 10 | # 2015-07-22 - first version 11 | # ------------------------------------------------ 12 | 13 | ###################################### 14 | # target 15 | ###################################### 16 | TARGET = 50x50_Bootloader 17 | 18 | 19 | ###################################### 20 | # building variables 21 | ###################################### 22 | # debug build? 23 | DEBUG = 1 24 | # optimization 25 | OPT = -Og 26 | 27 | 28 | ####################################### 29 | # paths 30 | ####################################### 31 | # Build path 32 | BUILD_DIR = build 33 | 34 | ###################################### 35 | # source 36 | ###################################### 37 | # C sources 38 | C_SOURCES = \ 39 | Core/Src/bootloader.c \ 40 | Core/Src/can.c \ 41 | Core/Src/main.c \ 42 | Core/Src/stm32g4xx_hal_msp.c \ 43 | Core/Src/stm32g4xx_hal_timebase_tim.c \ 44 | Core/Src/stm32g4xx_it.c \ 45 | Core/Src/system_stm32g4xx.c \ 46 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal.c \ 47 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_cortex.c \ 48 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_dma.c \ 49 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_dma_ex.c \ 50 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_exti.c \ 51 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_fdcan.c \ 52 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash.c \ 53 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash_ex.c \ 54 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash_ramfunc.c \ 55 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_gpio.c \ 56 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pcd.c \ 57 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pcd_ex.c \ 58 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr.c \ 59 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr_ex.c \ 60 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_rcc.c \ 61 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_rcc_ex.c \ 62 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_tim.c \ 63 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_tim_ex.c \ 64 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_ll_usb.c \ 65 | Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c \ 66 | Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c \ 67 | Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c \ 68 | Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c \ 69 | USB_Device/App/usb_device.c \ 70 | USB_Device/App/usbd_cdc_if.c \ 71 | USB_Device/App/usbd_desc.c \ 72 | USB_Device/Target/usbd_conf.c 73 | 74 | 75 | CPP_SOURCES = \ 76 | 77 | 78 | # ASM sources 79 | ASM_SOURCES = \ 80 | startup_stm32g431xx.s 81 | 82 | 83 | 84 | ####################################### 85 | # binaries 86 | ####################################### 87 | PREFIX = arm-none-eabi- 88 | POSTFIX = " 89 | # The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx) 90 | # either it can be added to the PATH environment variable. 91 | GCC_PATH="/Users/thomasg/Library/Application Support/Code/User/globalStorage/bmd.stm32-for-vscode/@xpack-dev-tools/arm-none-eabi-gcc/12.2.1-1.2.1/.content/bin 92 | ifdef GCC_PATH 93 | CXX = $(GCC_PATH)/$(PREFIX)g++$(POSTFIX) 94 | CC = $(GCC_PATH)/$(PREFIX)gcc$(POSTFIX) 95 | AS = $(GCC_PATH)/$(PREFIX)gcc$(POSTFIX) -x assembler-with-cpp 96 | CP = $(GCC_PATH)/$(PREFIX)objcopy$(POSTFIX) 97 | SZ = $(GCC_PATH)/$(PREFIX)size$(POSTFIX) 98 | else 99 | CXX = $(PREFIX)g++ 100 | CC = $(PREFIX)gcc 101 | AS = $(PREFIX)gcc -x assembler-with-cpp 102 | CP = $(PREFIX)objcopy 103 | SZ = $(PREFIX)size 104 | endif 105 | HEX = $(CP) -O ihex 106 | BIN = $(CP) -O binary -S 107 | 108 | ####################################### 109 | # CFLAGS 110 | ####################################### 111 | # cpu 112 | CPU = -mcpu=cortex-m4 113 | 114 | # fpu 115 | FPU = -mfpu=fpv4-sp-d16 116 | 117 | # float-abi 118 | FLOAT-ABI = -mfloat-abi=hard 119 | 120 | # mcu 121 | MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI) 122 | 123 | # macros for gcc 124 | # AS defines 125 | AS_DEFS = 126 | 127 | # C defines 128 | C_DEFS = \ 129 | -DSTM32G431xx \ 130 | -DUSE_HAL_DRIVER 131 | 132 | 133 | # CXX defines 134 | CXX_DEFS = \ 135 | -DSTM32G431xx \ 136 | -DUSE_HAL_DRIVER 137 | 138 | 139 | # AS includes 140 | AS_INCLUDES = \ 141 | 142 | # C includes 143 | C_INCLUDES = \ 144 | -ICore/Inc \ 145 | -IDrivers/CMSIS/Device/ST/STM32G4xx/Include \ 146 | -IDrivers/CMSIS/Include \ 147 | -IDrivers/STM32G4xx_HAL_Driver/Inc \ 148 | -IDrivers/STM32G4xx_HAL_Driver/Inc/Legacy \ 149 | -IMiddlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc \ 150 | -IMiddlewares/ST/STM32_USB_Device_Library/Core/Inc \ 151 | -IUSB_Device/App \ 152 | -IUSB_Device/Target 153 | 154 | 155 | 156 | # compile gcc flags 157 | ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections 158 | 159 | CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections 160 | 161 | CXXFLAGS = $(MCU) $(CXX_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections -feliminate-unused-debug-types 162 | 163 | ifeq ($(DEBUG), 1) 164 | CFLAGS += -g -gdwarf -ggdb 165 | CXXFLAGS += -g -gdwarf -ggdb 166 | endif 167 | 168 | # Add additional flags 169 | CFLAGS += -Wall -fdata-sections -ffunction-sections 170 | ASFLAGS += -Wall -fdata-sections -ffunction-sections 171 | CXXFLAGS += 172 | 173 | # Generate dependency information 174 | CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" 175 | CXXFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" 176 | 177 | ####################################### 178 | # LDFLAGS 179 | ####################################### 180 | # link script 181 | LDSCRIPT = STM32G431CBUx_FLASH.ld 182 | 183 | # libraries 184 | LIBS = -lc -lm -lnosys 185 | LIBDIR = \ 186 | 187 | 188 | # Additional LD Flags from config file 189 | ADDITIONALLDFLAGS = -specs=nano.specs 190 | 191 | LDFLAGS = $(MCU) $(ADDITIONALLDFLAGS) -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections 192 | 193 | # default action: build all 194 | all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin 195 | 196 | 197 | ####################################### 198 | # build the application 199 | ####################################### 200 | # list of cpp program objects 201 | OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(CPP_SOURCES:.cpp=.o))) 202 | vpath %.cpp $(sort $(dir $(CPP_SOURCES))) 203 | 204 | # list of C objects 205 | OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o))) 206 | vpath %.c $(sort $(dir $(C_SOURCES))) 207 | 208 | # list of ASM program objects 209 | # list of ASM program objects 210 | UPPER_CASE_ASM_SOURCES = $(filter %.S,$(ASM_SOURCES)) 211 | LOWER_CASE_ASM_SOURCES = $(filter %.s,$(ASM_SOURCES)) 212 | 213 | OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(UPPER_CASE_ASM_SOURCES:.S=.o))) 214 | OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(LOWER_CASE_ASM_SOURCES:.s=.o))) 215 | vpath %.s $(sort $(dir $(ASM_SOURCES))) 216 | 217 | $(BUILD_DIR)/%.o: %.cpp STM32Make.make | $(BUILD_DIR) 218 | $(CXX) -c $(CXXFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.cpp=.lst)) $< -o $@ 219 | 220 | $(BUILD_DIR)/%.o: %.cxx STM32Make.make | $(BUILD_DIR) 221 | $(CXX) -c $(CXXFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.cxx=.lst)) $< -o $@ 222 | 223 | $(BUILD_DIR)/%.o: %.c STM32Make.make | $(BUILD_DIR) 224 | $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@ 225 | 226 | $(BUILD_DIR)/%.o: %.s STM32Make.make | $(BUILD_DIR) 227 | $(AS) -c $(CFLAGS) $< -o $@ 228 | 229 | $(BUILD_DIR)/%.o: %.S STM32Make.make | $(BUILD_DIR) 230 | $(AS) -c $(CFLAGS) $< -o $@ 231 | 232 | $(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) STM32Make.make 233 | $(CC) $(OBJECTS) $(LDFLAGS) -o $@ 234 | $(SZ) $@ 235 | 236 | $(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR) 237 | $(HEX) $< $@ 238 | 239 | $(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR) 240 | $(BIN) $< $@ 241 | 242 | $(BUILD_DIR): 243 | mkdir $@ 244 | 245 | ####################################### 246 | # flash 247 | ####################################### 248 | flash: $(BUILD_DIR)/$(TARGET).elf 249 | "/Users/thomasg/Library/Application Support/Code/User/globalStorage/bmd.stm32-for-vscode/@xpack-dev-tools/openocd/0.12.0-1.1/.content/bin/openocd" -f ./openocd.cfg -c "program $(BUILD_DIR)/$(TARGET).elf verify reset exit" 250 | 251 | ####################################### 252 | # erase 253 | ####################################### 254 | erase: $(BUILD_DIR)/$(TARGET).elf 255 | "/Users/thomasg/Library/Application Support/Code/User/globalStorage/bmd.stm32-for-vscode/@xpack-dev-tools/openocd/0.12.0-1.1/.content/bin/openocd" -f ./openocd.cfg -c "init; reset halt; stm32g4x mass_erase 0; exit" 256 | 257 | ####################################### 258 | # clean up 259 | ####################################### 260 | clean: 261 | -rm -fR $(BUILD_DIR) 262 | 263 | ####################################### 264 | # custom makefile rules 265 | ####################################### 266 | 267 | 268 | 269 | ####################################### 270 | # dependencies 271 | ####################################### 272 | -include $(wildcard $(BUILD_DIR)/*.d) 273 | 274 | # *** EOF *** -------------------------------------------------------------------------------- /bootloader/USB_Device/App/usb_device.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : usb_device.c 5 | * @version : v3.0_Cube 6 | * @brief : This file implements the USB Device 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Includes ------------------------------------------------------------------*/ 22 | 23 | #include "usb_device.h" 24 | #include "usbd_core.h" 25 | #include "usbd_desc.h" 26 | #include "usbd_cdc.h" 27 | #include "usbd_cdc_if.h" 28 | 29 | /* USER CODE BEGIN Includes */ 30 | 31 | /* USER CODE END Includes */ 32 | 33 | /* USER CODE BEGIN PV */ 34 | /* Private variables ---------------------------------------------------------*/ 35 | 36 | /* USER CODE END PV */ 37 | 38 | /* USER CODE BEGIN PFP */ 39 | /* Private function prototypes -----------------------------------------------*/ 40 | 41 | /* USER CODE END PFP */ 42 | 43 | extern void Error_Handler(void); 44 | /* USB Device Core handle declaration. */ 45 | USBD_HandleTypeDef hUsbDeviceFS; 46 | extern USBD_DescriptorsTypeDef CDC_Desc; 47 | 48 | /* 49 | * -- Insert your variables declaration here -- 50 | */ 51 | /* USER CODE BEGIN 0 */ 52 | 53 | /* USER CODE END 0 */ 54 | 55 | /* 56 | * -- Insert your external function declaration here -- 57 | */ 58 | /* USER CODE BEGIN 1 */ 59 | 60 | /* USER CODE END 1 */ 61 | 62 | /** 63 | * Init USB device Library, add supported class and start the library 64 | * @retval None 65 | */ 66 | void MX_USB_Device_Init(void) 67 | { 68 | /* USER CODE BEGIN USB_Device_Init_PreTreatment */ 69 | 70 | /* USER CODE END USB_Device_Init_PreTreatment */ 71 | 72 | /* Init Device Library, add supported class and start the library. */ 73 | if (USBD_Init(&hUsbDeviceFS, &CDC_Desc, DEVICE_FS) != USBD_OK) { 74 | Error_Handler(); 75 | } 76 | if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK) { 77 | Error_Handler(); 78 | } 79 | if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK) { 80 | Error_Handler(); 81 | } 82 | if (USBD_Start(&hUsbDeviceFS) != USBD_OK) { 83 | Error_Handler(); 84 | } 85 | /* USER CODE BEGIN USB_Device_Init_PostTreatment */ 86 | 87 | /* USER CODE END USB_Device_Init_PostTreatment */ 88 | } 89 | 90 | /** 91 | * @} 92 | */ 93 | 94 | /** 95 | * @} 96 | */ 97 | 98 | -------------------------------------------------------------------------------- /bootloader/USB_Device/App/usb_device.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : usb_device.h 5 | * @version : v3.0_Cube 6 | * @brief : Header for usb_device.c file. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __USB_DEVICE__H__ 23 | #define __USB_DEVICE__H__ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Includes ------------------------------------------------------------------*/ 30 | #include "stm32g4xx.h" 31 | #include "stm32g4xx_hal.h" 32 | #include "usbd_def.h" 33 | 34 | /* USER CODE BEGIN INCLUDE */ 35 | 36 | /* USER CODE END INCLUDE */ 37 | 38 | /** @addtogroup USBD_OTG_DRIVER 39 | * @{ 40 | */ 41 | 42 | /** @defgroup USBD_DEVICE USBD_DEVICE 43 | * @brief Device file for Usb otg low level driver. 44 | * @{ 45 | */ 46 | 47 | /** @defgroup USBD_DEVICE_Exported_Variables USBD_DEVICE_Exported_Variables 48 | * @brief Public variables. 49 | * @{ 50 | */ 51 | 52 | /* Private variables ---------------------------------------------------------*/ 53 | /* USER CODE BEGIN PV */ 54 | 55 | /* USER CODE END PV */ 56 | 57 | /* Private function prototypes -----------------------------------------------*/ 58 | /* USER CODE BEGIN PFP */ 59 | 60 | /* USER CODE END PFP */ 61 | 62 | /* 63 | * -- Insert your variables declaration here -- 64 | */ 65 | /* USER CODE BEGIN VARIABLES */ 66 | 67 | /* USER CODE END VARIABLES */ 68 | /** 69 | * @} 70 | */ 71 | 72 | /** @defgroup USBD_DEVICE_Exported_FunctionsPrototype USBD_DEVICE_Exported_FunctionsPrototype 73 | * @brief Declaration of public functions for Usb device. 74 | * @{ 75 | */ 76 | 77 | /** USB Device initialization function. */ 78 | void MX_USB_Device_Init(void); 79 | 80 | /* 81 | * -- Insert functions declaration here -- 82 | */ 83 | /* USER CODE BEGIN FD */ 84 | 85 | /* USER CODE END FD */ 86 | /** 87 | * @} 88 | */ 89 | 90 | /** 91 | * @} 92 | */ 93 | 94 | /** 95 | * @} 96 | */ 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif 101 | 102 | #endif /* __USB_DEVICE__H__ */ 103 | 104 | -------------------------------------------------------------------------------- /bootloader/USB_Device/App/usbd_cdc_if.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : usbd_cdc_if.h 5 | * @version : v3.0_Cube 6 | * @brief : Header for usbd_cdc_if.c file. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __USBD_CDC_IF_H__ 23 | #define __USBD_CDC_IF_H__ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Includes ------------------------------------------------------------------*/ 30 | #include "usbd_cdc.h" 31 | 32 | /* USER CODE BEGIN INCLUDE */ 33 | 34 | /* USER CODE END INCLUDE */ 35 | 36 | /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY 37 | * @brief For Usb device. 38 | * @{ 39 | */ 40 | 41 | /** @defgroup USBD_CDC_IF USBD_CDC_IF 42 | * @brief Usb VCP device module 43 | * @{ 44 | */ 45 | 46 | /** @defgroup USBD_CDC_IF_Exported_Defines USBD_CDC_IF_Exported_Defines 47 | * @brief Defines. 48 | * @{ 49 | */ 50 | /* Define size for the receive and transmit buffer over CDC */ 51 | #define APP_RX_DATA_SIZE 1024 52 | #define APP_TX_DATA_SIZE 1024 53 | /* USER CODE BEGIN EXPORTED_DEFINES */ 54 | 55 | /* USER CODE END EXPORTED_DEFINES */ 56 | 57 | /** 58 | * @} 59 | */ 60 | 61 | /** @defgroup USBD_CDC_IF_Exported_Types USBD_CDC_IF_Exported_Types 62 | * @brief Types. 63 | * @{ 64 | */ 65 | 66 | /* USER CODE BEGIN EXPORTED_TYPES */ 67 | 68 | /* USER CODE END EXPORTED_TYPES */ 69 | 70 | /** 71 | * @} 72 | */ 73 | 74 | /** @defgroup USBD_CDC_IF_Exported_Macros USBD_CDC_IF_Exported_Macros 75 | * @brief Aliases. 76 | * @{ 77 | */ 78 | 79 | /* USER CODE BEGIN EXPORTED_MACRO */ 80 | 81 | /* USER CODE END EXPORTED_MACRO */ 82 | 83 | /** 84 | * @} 85 | */ 86 | 87 | /** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables 88 | * @brief Public variables. 89 | * @{ 90 | */ 91 | 92 | /** CDC Interface callback. */ 93 | extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; 94 | 95 | /* USER CODE BEGIN EXPORTED_VARIABLES */ 96 | 97 | /* USER CODE END EXPORTED_VARIABLES */ 98 | 99 | /** 100 | * @} 101 | */ 102 | 103 | /** @defgroup USBD_CDC_IF_Exported_FunctionsPrototype USBD_CDC_IF_Exported_FunctionsPrototype 104 | * @brief Public functions declaration. 105 | * @{ 106 | */ 107 | 108 | uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len); 109 | 110 | /* USER CODE BEGIN EXPORTED_FUNCTIONS */ 111 | 112 | /* USER CODE END EXPORTED_FUNCTIONS */ 113 | 114 | /** 115 | * @} 116 | */ 117 | 118 | /** 119 | * @} 120 | */ 121 | 122 | /** 123 | * @} 124 | */ 125 | 126 | #ifdef __cplusplus 127 | } 128 | #endif 129 | 130 | #endif /* __USBD_CDC_IF_H__ */ 131 | 132 | -------------------------------------------------------------------------------- /bootloader/USB_Device/App/usbd_desc.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : usbd_desc.c 5 | * @version : v3.0_Cube 6 | * @brief : Header for usbd_conf.c file. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __USBD_DESC__C__ 23 | #define __USBD_DESC__C__ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Includes ------------------------------------------------------------------*/ 30 | #include "usbd_def.h" 31 | 32 | /* USER CODE BEGIN INCLUDE */ 33 | 34 | /* USER CODE END INCLUDE */ 35 | 36 | /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY 37 | * @{ 38 | */ 39 | 40 | /** @defgroup USBD_DESC USBD_DESC 41 | * @brief Usb device descriptors module. 42 | * @{ 43 | */ 44 | 45 | /** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants 46 | * @brief Constants. 47 | * @{ 48 | */ 49 | #define DEVICE_ID1 (UID_BASE) 50 | #define DEVICE_ID2 (UID_BASE + 0x4) 51 | #define DEVICE_ID3 (UID_BASE + 0x8) 52 | 53 | #define USB_SIZ_STRING_SERIAL 0x1A 54 | 55 | /* USER CODE BEGIN EXPORTED_CONSTANTS */ 56 | 57 | /* USER CODE END EXPORTED_CONSTANTS */ 58 | 59 | /** 60 | * @} 61 | */ 62 | 63 | /** @defgroup USBD_DESC_Exported_Defines USBD_DESC_Exported_Defines 64 | * @brief Defines. 65 | * @{ 66 | */ 67 | 68 | /* USER CODE BEGIN EXPORTED_DEFINES */ 69 | 70 | /* USER CODE END EXPORTED_DEFINES */ 71 | 72 | /** 73 | * @} 74 | */ 75 | 76 | /** @defgroup USBD_DESC_Exported_TypesDefinitions USBD_DESC_Exported_TypesDefinitions 77 | * @brief Types. 78 | * @{ 79 | */ 80 | 81 | /* USER CODE BEGIN EXPORTED_TYPES */ 82 | 83 | /* USER CODE END EXPORTED_TYPES */ 84 | 85 | /** 86 | * @} 87 | */ 88 | 89 | /** @defgroup USBD_DESC_Exported_Macros USBD_DESC_Exported_Macros 90 | * @brief Aliases. 91 | * @{ 92 | */ 93 | 94 | /* USER CODE BEGIN EXPORTED_MACRO */ 95 | 96 | /* USER CODE END EXPORTED_MACRO */ 97 | 98 | /** 99 | * @} 100 | */ 101 | 102 | /** @defgroup USBD_DESC_Exported_Variables USBD_DESC_Exported_Variables 103 | * @brief Public variables. 104 | * @{ 105 | */ 106 | 107 | extern USBD_DescriptorsTypeDef CDC_Desc; 108 | 109 | /* USER CODE BEGIN EXPORTED_VARIABLES */ 110 | 111 | /* USER CODE END EXPORTED_VARIABLES */ 112 | 113 | /** 114 | * @} 115 | */ 116 | 117 | /** @defgroup USBD_DESC_Exported_FunctionsPrototype USBD_DESC_Exported_FunctionsPrototype 118 | * @brief Public functions declaration. 119 | * @{ 120 | */ 121 | 122 | /* USER CODE BEGIN EXPORTED_FUNCTIONS */ 123 | 124 | /* USER CODE END EXPORTED_FUNCTIONS */ 125 | 126 | /** 127 | * @} 128 | */ 129 | 130 | /** 131 | * @} 132 | */ 133 | 134 | /** 135 | * @} 136 | */ 137 | 138 | #ifdef __cplusplus 139 | } 140 | #endif 141 | 142 | #endif /* __USBD_DESC__C__ */ 143 | 144 | -------------------------------------------------------------------------------- /bootloader/USB_Device/Target/usbd_conf.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : usbd_conf.h 5 | * @version : v3.0_Cube 6 | * @brief : Header for usbd_conf.c file. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __USBD_CONF__H__ 23 | #define __USBD_CONF__H__ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Includes ------------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include 33 | #include "stm32g4xx.h" 34 | #include "stm32g4xx_hal.h" 35 | 36 | /* USER CODE BEGIN INCLUDE */ 37 | 38 | /* USER CODE END INCLUDE */ 39 | 40 | /** @addtogroup USBD_OTG_DRIVER 41 | * @brief Driver for Usb device. 42 | * @{ 43 | */ 44 | 45 | /** @defgroup USBD_CONF USBD_CONF 46 | * @brief Configuration file for Usb otg low level driver. 47 | * @{ 48 | */ 49 | 50 | /** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables 51 | * @brief Public variables. 52 | * @{ 53 | */ 54 | 55 | /* Private variables ---------------------------------------------------------*/ 56 | /* USER CODE BEGIN PV */ 57 | /* USER CODE END PV */ 58 | /** 59 | * @} 60 | */ 61 | 62 | /** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines 63 | * @brief Defines for configuration of the Usb device. 64 | * @{ 65 | */ 66 | 67 | /*---------- -----------*/ 68 | #define USBD_MAX_NUM_INTERFACES 1U 69 | /*---------- -----------*/ 70 | #define USBD_MAX_NUM_CONFIGURATION 1U 71 | /*---------- -----------*/ 72 | #define USBD_MAX_STR_DESC_SIZ 512U 73 | /*---------- -----------*/ 74 | #define USBD_DEBUG_LEVEL 1U 75 | /*---------- -----------*/ 76 | #define USBD_LPM_ENABLED 1U 77 | /*---------- -----------*/ 78 | #define USBD_SELF_POWERED 0U 79 | 80 | /****************************************/ 81 | /* #define for FS and HS identification */ 82 | #define DEVICE_FS 0 83 | 84 | /** 85 | * @} 86 | */ 87 | 88 | /** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros 89 | * @brief Aliases. 90 | * @{ 91 | */ 92 | 93 | /* Memory management macros */ 94 | 95 | /** Alias for memory allocation. */ 96 | #define USBD_malloc (void *)USBD_static_malloc 97 | 98 | /** Alias for memory release. */ 99 | #define USBD_free USBD_static_free 100 | 101 | /** Alias for memory set. */ 102 | #define USBD_memset memset 103 | 104 | /** Alias for memory copy. */ 105 | #define USBD_memcpy memcpy 106 | 107 | /** Alias for delay. */ 108 | #define USBD_Delay HAL_Delay 109 | 110 | /* DEBUG macros */ 111 | 112 | #if (USBD_DEBUG_LEVEL > 0) 113 | #define USBD_UsrLog(...) printf(__VA_ARGS__);\ 114 | printf("\n"); 115 | #else 116 | #define USBD_UsrLog(...) 117 | #endif 118 | 119 | #if (USBD_DEBUG_LEVEL > 1) 120 | 121 | #define USBD_ErrLog(...) printf("ERROR: ") ;\ 122 | printf(__VA_ARGS__);\ 123 | printf("\n"); 124 | #else 125 | #define USBD_ErrLog(...) 126 | #endif 127 | 128 | #if (USBD_DEBUG_LEVEL > 2) 129 | #define USBD_DbgLog(...) printf("DEBUG : ") ;\ 130 | printf(__VA_ARGS__);\ 131 | printf("\n"); 132 | #else 133 | #define USBD_DbgLog(...) 134 | #endif 135 | 136 | /** 137 | * @} 138 | */ 139 | 140 | /** @defgroup USBD_CONF_Exported_Types USBD_CONF_Exported_Types 141 | * @brief Types. 142 | * @{ 143 | */ 144 | 145 | /** 146 | * @} 147 | */ 148 | 149 | /** @defgroup USBD_CONF_Exported_FunctionsPrototype USBD_CONF_Exported_FunctionsPrototype 150 | * @brief Declaration of public functions for Usb device. 151 | * @{ 152 | */ 153 | 154 | /* Exported functions -------------------------------------------------------*/ 155 | void *USBD_static_malloc(uint32_t size); 156 | void USBD_static_free(void *p); 157 | 158 | /** 159 | * @} 160 | */ 161 | 162 | /** 163 | * @} 164 | */ 165 | 166 | /** 167 | * @} 168 | */ 169 | 170 | #ifdef __cplusplus 171 | } 172 | #endif 173 | 174 | #endif /* __USBD_CONF__H__ */ 175 | 176 | -------------------------------------------------------------------------------- /bootloader/openocd.cfg: -------------------------------------------------------------------------------- 1 | #OpenOCD configuration file, generated by STM32 for VSCode 2 | 3 | # Programmer, can be changed to several interfaces 4 | # Standard will be the stlink interface as this is the standard for STM32 dev boards 5 | source [find interface/stlink.cfg] 6 | 7 | # The target MCU. This should match your board 8 | source [find target/stm32g4x.cfg] 9 | -------------------------------------------------------------------------------- /bootloader/python/convert_hex.py: -------------------------------------------------------------------------------- 1 | from read_hex import convert_to_16bit_aligned 2 | 3 | convert_to_16bit_aligned("../../firmware/build/50x50_DRIVE.hex") -------------------------------------------------------------------------------- /bootloader/python/enter_app.py: -------------------------------------------------------------------------------- 1 | import serial 2 | from serial.tools import list_ports 3 | import time 4 | 5 | COM_PORT = None 6 | 7 | for port in list_ports.comports(): 8 | if(port.description == "50x50-Drive USB2CAN"): 9 | COM_PORT = port.device 10 | 11 | if(COM_PORT == None): 12 | raise Exception("No interface found") 13 | 14 | print("Interface found on", COM_PORT) 15 | 16 | ser = serial.Serial(COM_PORT, 115200) 17 | # time.sleep(0.1) 18 | 19 | ######## Command a flash erase 20 | print("Entering bootloader") 21 | ser.write(bytes('BTL\r', 'utf-8')) 22 | time.sleep(0.5) 23 | 24 | COM_PORT = None 25 | 26 | while(COM_PORT == None): 27 | time.sleep(0.1) 28 | print("Checking for USB interface") 29 | for port in list_ports.comports(): 30 | if(port.description == "50x50-Drive USB2CAN"): 31 | COM_PORT = port.device 32 | break 33 | 34 | print("Interface found on", COM_PORT) 35 | 36 | # time.sleep(0.1) 37 | ser = serial.Serial(COM_PORT, 115200) 38 | 39 | print("Entering app") 40 | ser.write(bytes('APP\r', 'utf-8')) -------------------------------------------------------------------------------- /bootloader/python/enter_bootloader.py: -------------------------------------------------------------------------------- 1 | import serial 2 | from serial.tools import list_ports 3 | import time 4 | 5 | for port in list_ports.comports(): 6 | if(port.description == "50x50-Drive USB2CAN"): 7 | COM_PORT = port.device 8 | 9 | if(COM_PORT == None): 10 | raise Exception("No interface found") 11 | 12 | print("Interface found on", COM_PORT) 13 | 14 | ser = serial.Serial(COM_PORT, 115200) 15 | time.sleep(0.1) 16 | 17 | ######## Command a flash erase 18 | print("Entering program flash") 19 | ser.write(bytes('BTL\r', 'utf-8')) -------------------------------------------------------------------------------- /bootloader/python/flash_CAN.py: -------------------------------------------------------------------------------- 1 | import can 2 | import serial 3 | from serial.tools import list_ports 4 | import time 5 | import stm32bootloader 6 | from read_hex import convert_to_16bit_aligned 7 | 8 | convert_to_16bit_aligned("../../firmware/build/50x50_DRIVE.hex") 9 | 10 | COM_PORT = stm32bootloader.find_port() 11 | 12 | bus = can.Bus(interface="slcan", channel=COM_PORT, ttyBaudrate = 115200) 13 | bus.set_bitrate(500_000) 14 | 15 | def build_byte_msg(byte_array): 16 | return can.Message( 17 | arbitration_id=69, 18 | data=byte_array, 19 | is_extended_id=False 20 | ) 21 | 22 | print("Entering bootloader") 23 | bus.send(build_byte_msg(bytearray("BTL", "utf-8"))) 24 | time.sleep(0.5) 25 | 26 | # print("Clearing flash") 27 | # bus.send(build_byte_msg(bytearray("CLR", "utf-8"))) 28 | # bus.recv() 29 | 30 | # file = open("16_bit_aligned.hex", "r") 31 | 32 | # for line in file: 33 | # # print(line) 34 | # record_type = line[7:9] 35 | # address = line[3:7] 36 | # print(address) 37 | # if(record_type == '00'): 38 | # data_length = line[1:3] 39 | # data_length_int = int(data_length, 16) 40 | 41 | # data = line[9:9 + 2 * data_length_int] 42 | # data_list = list(bytearray.fromhex(data)) 43 | # print(data_list) 44 | 45 | # print(data_list[0:8]) 46 | # bus.send(build_byte_msg(data_list[0:8])) 47 | # bus.recv() 48 | 49 | # time.sleep(0.001) 50 | 51 | # if(data_length_int == 16): 52 | # # print(build_byte_msg(data_list[8:16])) 53 | # bus.send(build_byte_msg(data_list[8:16])) 54 | # bus.recv() 55 | # time.sleep(0.001) 56 | 57 | # # time.sleep(0.01) 58 | 59 | # bus.send(build_byte_msg([])) 60 | # bus.recv() 61 | 62 | # time.sleep(0.2) 63 | 64 | # print("Entering app") 65 | # bus.send(build_byte_msg(bytearray("APP", "utf-8"))) 66 | # time.sleep(0.2) 67 | 68 | # print("Done") 69 | 70 | bus.shutdown() 71 | 72 | # bus.shutdown() 73 | 74 | -------------------------------------------------------------------------------- /bootloader/python/flash_USB.py: -------------------------------------------------------------------------------- 1 | from read_hex import convert_to_16bit_aligned 2 | import stm32bootloader 3 | 4 | convert_to_16bit_aligned("../../firmware/build/50x50_DRIVE.hex") 5 | 6 | # print("Entering bootloader") 7 | # stm32bootloader.enter_bootloader() 8 | print("Flashing") 9 | stm32bootloader.flash_hex_USB() 10 | print() 11 | print("Entering app") 12 | stm32bootloader.enter_app() -------------------------------------------------------------------------------- /bootloader/python/progress_bar_test.py: -------------------------------------------------------------------------------- 1 | import time 2 | import progressbar 3 | 4 | bar = progressbar.ProgressBar(max_value=200) 5 | for i in range(200): 6 | time.sleep(0.1) 7 | bar.update(i) -------------------------------------------------------------------------------- /bootloader/python/read_hex.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | 4 | def int_to_hexstr(data, digits): 5 | return f'{data:0{digits}x}' 6 | 7 | def convert_to_16bit_aligned(filepath): 8 | # Open file 9 | file = open(filepath, "r") 10 | 11 | full_data = [] 12 | full_data_address = 0 13 | 14 | memory_address = 0x0000 15 | 16 | MEM_START_OFFSET = 0x08008000 17 | 18 | for data_line in file: 19 | data_line = data_line[1:-1] 20 | data_length = data_line[0:2] 21 | data_length_int = int(data_length, 16) 22 | 23 | address = data_line[2:6] 24 | int_address = int(address, 16) 25 | record_type = data_line[6:8] 26 | 27 | if(record_type == "04"): 28 | address_second_half = int(data_line[8:12], 16) 29 | 30 | memory_address = (int_address & 0xFFFFF) | address_second_half << 8*2 31 | 32 | if(record_type == "00"): 33 | offset_address = memory_address - MEM_START_OFFSET 34 | 35 | while(full_data_address != offset_address): 36 | 37 | full_data += ['0', '0'] # Add null byte 38 | full_data_address += 1 # Add byte 39 | 40 | data = data_line[8:8 + 2 * data_length_int] 41 | full_data += data 42 | 43 | full_data_address += data_length_int 44 | 45 | file.close() 46 | 47 | 48 | full_data_split = [] 49 | counter = 0 50 | new_row = [] 51 | for byte in full_data: 52 | new_row.append(byte) 53 | counter += 1 54 | if(counter == 16 * 2): 55 | counter = 0 56 | full_data_split.append(new_row) 57 | new_row = [] 58 | 59 | out_file = "" 60 | address_value = 0 61 | for row in full_data_split: 62 | out_line = ":" 63 | 64 | row = np.array(row) 65 | 66 | data_line = "".join(row) 67 | 68 | # DATA LENGTH 69 | out_line += int_to_hexstr(int(len(data_line)/2), 2) + "" 70 | 71 | # ADDRESS 72 | out_line += int_to_hexstr(address_value, 4) + "" 73 | 74 | # RECORD TYPE 75 | out_line += "00" 76 | 77 | # DATA 78 | out_line += data_line 79 | 80 | # Checksum 81 | # TODO: Actually make this work 82 | out_line += "FF" 83 | 84 | # print(out_line) 85 | out_file += out_line + "\r" 86 | address_value += 16 87 | 88 | f = open("16_bit_aligned.hex", "w") 89 | f.write(out_file) 90 | f.close() 91 | 92 | if(__name__ == "__main__"): 93 | convert_to_16bit_aligned("../../firmware/build/50x50_DRIVE.hex") 94 | print("DONE") 95 | -------------------------------------------------------------------------------- /bootloader/python/send_hex.py: -------------------------------------------------------------------------------- 1 | import serial 2 | from serial.tools import list_ports 3 | import time 4 | 5 | def num_lines(file): 6 | num_lines = 0 7 | for line in file: 8 | num_lines += 1 9 | 10 | return num_lines 11 | 12 | ######## Find port 13 | COM_PORT = None 14 | 15 | for port in list_ports.comports(): 16 | if(port.description == "50x50-Drive USB2CAN"): 17 | COM_PORT = port.device 18 | 19 | if(COM_PORT == None): 20 | raise Exception("No interface found") 21 | 22 | print("Board found on", COM_PORT) 23 | 24 | ser = serial.Serial(COM_PORT, 115200) 25 | time.sleep(0.1) 26 | 27 | ######## Command a flash erase 28 | print("> Erasing flash") 29 | ser.write(bytes('CLR\r', 'utf-8')) 30 | ret = ser.read_until(b'\r') 31 | print("DONE") 32 | 33 | ######## Open file 34 | # file = open("/Users/thomasg/Documents/github/50x50_Bootloader/build/50x50_Bootloader.hex", "r") 35 | # total_lines = num_lines(file) 36 | # file.close() 37 | 38 | 39 | # file = open("/Users/thomasg/Documents/github/50x50_Bootloader/build/50x50_Bootloader.hex", "r") 40 | file = open("16_bit_aligned.hex", "r") 41 | 42 | # ELAR = file.readline()[1:-1] 43 | # print(ELAR) 44 | 45 | def print_hex_list(data_list): 46 | print_string = "" 47 | for byte in data_list: 48 | print_string += hex(byte) + " " 49 | print(print_string) 50 | 51 | 52 | print("> Flashing new firmware") 53 | line_num = 0 54 | for line in file: 55 | # print(line) 56 | 57 | record_type = line[7:9] 58 | address = line[3:7] 59 | if(record_type == '00'): 60 | data_length = line[1:3] 61 | data_length_int = int(data_length, 16) 62 | 63 | data = line[9:9 + 2 * data_length_int] 64 | data_list = list(bytearray.fromhex(data)) 65 | 66 | # print(address) 67 | # print_hex_list(data_list) 68 | 69 | ser.write(bytes(line[:-1] + '\r', 'utf-8')) 70 | 71 | ret = ser.read_until(b'\r') 72 | # time.sleep(0.01) 73 | line_num += 1 74 | else: 75 | # print(record_type) 76 | # print(line) 77 | # print() 78 | pass 79 | 80 | print("DONE") 81 | 82 | ser.close() 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /bootloader/python/stm32bootloader.py: -------------------------------------------------------------------------------- 1 | import time 2 | import serial 3 | from serial.tools import list_ports 4 | import progressbar 5 | 6 | def find_port(dev_name = "50x50-Drive"): 7 | COM_PORT = None 8 | 9 | attempts = 0 10 | 11 | while(COM_PORT == None): 12 | attempts+=1 13 | time.sleep(0.1) 14 | 15 | for port in list_ports.comports(): 16 | if(port.description == dev_name): 17 | COM_PORT = port.device 18 | break 19 | if(attempts > 100): 20 | raise Exception("Timeout") 21 | 22 | return COM_PORT 23 | 24 | def enter_bootloader(): 25 | COM_PORT = find_port() 26 | ser = serial.Serial(COM_PORT, 115200) 27 | ser.write(bytes('BTL\r', 'utf-8')) 28 | ser.close() 29 | 30 | 31 | def enter_app(): 32 | COM_PORT = find_port("50x50-Drive-Bootloader") 33 | ser = serial.Serial(COM_PORT, 115200) 34 | ser.write(bytes('APP\r', 'utf-8')) 35 | ser.close() 36 | 37 | def flash_hex_USB(): 38 | COM_PORT = find_port("50x50-Drive-Bootloader") 39 | ser = serial.Serial(COM_PORT, 115200) 40 | 41 | ######## Command a flash erase 42 | print(" Erasing flash") 43 | ser.write(bytes('CLR\r', 'utf-8')) 44 | ret = ser.read_until(b'\r') 45 | print("DONE") 46 | 47 | ######## Flash new firmware 48 | file = open("16_bit_aligned.hex", "r") 49 | num_lines = 0 50 | for line in file: 51 | num_lines += 1 52 | file.close() 53 | 54 | 55 | bar = progressbar.ProgressBar(max_value=num_lines) 56 | 57 | file = open("16_bit_aligned.hex", "r") 58 | 59 | print(" Flashing new firmware") 60 | line_num = 0 61 | for line in file: 62 | record_type = line[7:9] 63 | address = line[3:7] 64 | if(record_type == '00'): 65 | data_length = line[1:3] 66 | data_length_int = int(data_length, 16) 67 | 68 | data = line[9:9 + 2 * data_length_int] 69 | data_list = list(bytearray.fromhex(data)) 70 | 71 | ser.write(bytes(line[:-1] + '\r', 'utf-8')) 72 | 73 | ret = ser.read_until(b'\r') 74 | line_num += 1 75 | bar.update(line_num) 76 | else: 77 | 78 | pass 79 | 80 | ser.close() 81 | 82 | 83 | def print_hex_list(data_list): 84 | print_string = "" 85 | for byte in data_list: 86 | print_string += hex(byte) + " " 87 | print(print_string) -------------------------------------------------------------------------------- /docs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LegoYoda112/BLDC_Driver/ad5e74cb48fdc431fb3d7c20c6390ad6ad415936/docs/.DS_Store -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # For the full list of built-in configuration values, see the documentation: 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 5 | 6 | 7 | 8 | # # Build doxygen 9 | import subprocess 10 | subprocess.call(['doxygen Doxyfile.in'], shell=True) 11 | 12 | # -- Project information ----------------------------------------------------- 13 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 14 | 15 | project = '50x50 Drive' 16 | copyright = '2023' 17 | author = 'Thomas Godden' 18 | release = '0.0' 19 | 20 | # -- General configuration --------------------------------------------------- 21 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 22 | 23 | extensions = ["breathe", 24 | "myst_parser"] 25 | 26 | myst_enable_extensions = ["colon_fence"] 27 | 28 | templates_path = ['_templates'] 29 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 30 | 31 | breathe_projects = { 32 | "firmware": "./_doxygen_build/xml/" 33 | } 34 | breathe_default_project = "firmware" 35 | 36 | 37 | 38 | # -- Options for HTML output ------------------------------------------------- 39 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 40 | 41 | html_theme = 'furo' 42 | html_static_path = ['_static'] -------------------------------------------------------------------------------- /docs/firmware/app.md: -------------------------------------------------------------------------------- 1 | # App 2 | `app.c` contains state machines run in the RTOS. 3 | 4 | ## Functions 5 | ```{eval-rst} 6 | .. doxygenfunction:: app_setup 7 | .. doxygenfunction:: app_status_led_task 8 | ``` -------------------------------------------------------------------------------- /docs/firmware/comms.md: -------------------------------------------------------------------------------- 1 | # Comms 2 | Comms.c includes all communication functions 3 | 4 | ```{eval-rst} 5 | .. doxygenfunction:: process_USB_rx 6 | ``` -------------------------------------------------------------------------------- /docs/firmware/drive.md: -------------------------------------------------------------------------------- 1 | # Drive 2 | Drive.c includes motor drive related functions, 3 | 4 | ## Variables 5 | ```{eval-rst} 6 | .. doxygenvariable:: enc_angle_int 7 | .. doxygenvariable:: electrical_angle_offset 8 | ``` 9 | 10 | 11 | ## Functions 12 | 13 | ### Calibration and Diagnostic 14 | 15 | ```{eval-rst} 16 | .. doxygenfunction:: estimate_phase_resistance 17 | .. doxygenfunction:: check_supply_voltage 18 | ``` 19 | 20 | ### Gate drive 21 | ```{eval-rst} 22 | .. doxygenfunction:: set_duty_phase_A 23 | .. doxygenfunction:: set_duty_phase_B 24 | .. doxygenfunction:: set_duty_phase_C 25 | .. doxygenfunction:: set_duty_phases 26 | ``` -------------------------------------------------------------------------------- /docs/firmware/foc.md: -------------------------------------------------------------------------------- 1 | # FOC 2 | `foc.h` contains the foc interrupt and related functions. 3 | 4 | 5 | ```{eval-rst} 6 | .. doxygenfunction:: set_current_setpoints 7 | .. doxygenfunction:: foc_interrupt 8 | .. doxygenfunction:: clarke_transform 9 | .. doxygenfunction:: park_transform 10 | .. doxygenfunction:: inverse_clarke_transform 11 | .. doxygenfunction:: inverse_park_transform 12 | ``` -------------------------------------------------------------------------------- /docs/firmware/index.md: -------------------------------------------------------------------------------- 1 | # Firmware 2 | :::{note} 3 | Firmware is highly in flux and this documentation is mostly a notepad for myself as I work on it. 4 | ::: 5 | 6 | ```{toctree} 7 | :maxdepth 1 8 | comms 9 | drive 10 | foc 11 | app 12 | ``` -------------------------------------------------------------------------------- /docs/hardware/index.md: -------------------------------------------------------------------------------- 1 | # Hardware 2 | 3 | ## Project link 4 | Current hardware files are on EasyEDA and will likely stay until fixes for V0 are done. I am targeting switching to KiCad for V1. 5 | 6 | [Project Link](https://oshwlab.com/pipdeream_thomas/bldc_driver_v0) 7 | 8 | ## Connectors and Pinout 9 | The board has an XT30 power in plug, 2 daisy chainable CAN and 5V connectors, 1 USB-C plug, 1 Serial Wire Debug header. It also has a bank of 4 dip switches, one of which (4) is a CAN termination resistor and the rest are for whatever you want! (will likely default to be bits to set CAN-ID; having to set IDs in software kind of sucks) 10 | 11 | ![Connectors](media/connectors.jpg "Connectors") 12 | 13 | ## Components and Layout 14 | The board is built around a [DRV8323HRTA](https://www.ti.com/product/DRV8323) gate driver chip from TI. The FET layout is very similar to the reference implementation (11.2 in the manual). 15 | 16 | A [STM32G431Cx6](https://www.st.com/en/microcontrollers-microprocessors/stm32g431c6.html) is the MCU of choice, it's fast-enough, fairly available, cost effective and has just enough bells and whistles to be fun (CAN-FD, FPU, some math accelerators, USB crystal trimming). 17 | 18 | :::{note} 19 | There is currently no HSE, so all timing is done off the internal STM crystal, this might become an issue at some point but seems to be fine for now. 20 | ::: 21 | 22 | The encoder is a [TLE5012BE1000](https://www.infineon.com/cms/en/product/sensor/magnetic-sensors/magnetic-position-sensors/angle-sensors/tle5012b-e1000/) an absolute magnetic encoder, which comes pre-flashed to provide quadrature outputs, with a pulse train given at startup to set the absolute offset. This is why there is a separate encoder 3.3V power rail hooked up to a transistor to power cycle it. 23 | 24 | :::{admonition} Tangent 25 | :class: note 26 | I've had some back and forth over whether it's better to just interface with the encoder directly using it's comms protocol, I'm pretty sure the quadrature interface is faster, but you need to do the odd off/on routine to get it to index absolutely correctly. Future iterations will likely add the digital interface, then just drop back to quadrature for actual commutation. 27 | ::: 28 | 29 | 30 | ![Components](media/components.jpg "Components") 31 | 32 | 33 | ## Hardware Errors 34 | 35 | ```{toctree} 36 | :maxdepth 1 37 | known-faults 38 | ``` -------------------------------------------------------------------------------- /docs/hardware/known-faults.md: -------------------------------------------------------------------------------- 1 | # Known faults 2 | List of known hardware faults in V0.0 hardware. 3 | 4 | 5 | ## Faults 6 | :::{warning} 7 | i2c line is missing pull-ups 8 | ::: 9 | 10 | :::{warning} 11 | USB-C power pulldowns are actually pullups 12 | ::: 13 | 14 | :::{warning} 15 | Silkscreen has incorrect polarity on XT30 connector 16 | ::: 17 | 18 | :::{warning} 19 | The 5V->3.3V regulator and DRV 3.3V regulator are hooked into the same net with no diode. This doesn't directly seem to cause any problems, other than the drive not turning off when you remove 5V power but keep motor power on. Future iterations will likely just not attach the DRV regulator output, as there is minimal need for the MCU to operate when it does not have either a CAN or USB connection. 20 | ::: 21 | 22 | ## Unknown source faults 23 | 24 | :::{warning} 25 | Seeing what I believe is a thermal shutdown on the DRV chip at higher voltages and speeds. Guessing it's the drive level set too high. Need to diagnose. 26 | ::: -------------------------------------------------------------------------------- /docs/hardware/media/components.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LegoYoda112/BLDC_Driver/ad5e74cb48fdc431fb3d7c20c6390ad6ad415936/docs/hardware/media/components.jpg -------------------------------------------------------------------------------- /docs/hardware/media/connectors.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LegoYoda112/BLDC_Driver/ad5e74cb48fdc431fb3d7c20c6390ad6ad415936/docs/hardware/media/connectors.jpg -------------------------------------------------------------------------------- /docs/hardware/media/drive-front-back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LegoYoda112/BLDC_Driver/ad5e74cb48fdc431fb3d7c20c6390ad6ad415936/docs/hardware/media/drive-front-back.jpg -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # 50x50 Drive 2 | 3 | ![50x50 Drive](hardware/media/drive-front-back.jpg "50x50 Drive") 4 | 5 | :::{admonition} Disclaimer 6 | :class: warning 7 | Read/Use at your own risk! Don't assume I know what I'm doing... because I don't. Also this is V0! 8 | ::: 9 | 10 | This is the documentation for the hardware, firmware and software for the 50x50 drive, a low-cost brushless motor controller. 11 | 12 | The two main objectives for this project are 13 | 1. Come out of it with a good-enough-to-be-useful low-cost (sub $30) brushless motor controller 14 | 1. Learn things (and have fun while doing that!) 15 | 16 | Objective 2 means that a lot of things in this project are going to be homebrew, part because it's a good learning experience and part because it's sometimes fun to go through the process of reinventing the wheel. 17 | 18 | This, coupled with objective 1's "good enough" requirement mean that plenty of the implementation is minimal and quick, targeted at being easy to understand, debug and fix. 19 | 20 | ## Documentation Contents 21 | ```{toctree} 22 | :maxdepth: 2 23 | hardware/index 24 | firmware/index 25 | ``` 26 | 27 | ## Other 28 | ### References 29 | - [Simple-FOC](https://simplefoc.com/) has a fantastic, well-documented FOC implementation 30 | - [Ben Katz's thesis](https://dspace.mit.edu/handle/1721.1/118671) 31 | - [MJBOTS](https://mjbots.com/products/moteus-n1) which has a very similar form factor board that you should probably get if you're interested in this project but are willing to pay some more. -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx==7.2.6 2 | myst-parser==2.0.0 3 | breathe==4.35.0 4 | furo==2023.9.10 -------------------------------------------------------------------------------- /firmware/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LegoYoda112/BLDC_Driver/ad5e74cb48fdc431fb3d7c20c6390ad6ad415936/firmware/.DS_Store -------------------------------------------------------------------------------- /firmware/Core/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LegoYoda112/BLDC_Driver/ad5e74cb48fdc431fb3d7c20c6390ad6ad415936/firmware/Core/.DS_Store -------------------------------------------------------------------------------- /firmware/Core/Inc/FreeRTOSConfig.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /* 3 | * FreeRTOS Kernel V10.3.1 4 | * Portion Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 5 | * Portion Copyright (C) 2019 StMicroelectronics, Inc. All Rights Reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | * http://www.FreeRTOS.org 25 | * http://aws.amazon.com/freertos 26 | * 27 | * 1 tab == 4 spaces! 28 | */ 29 | /* USER CODE END Header */ 30 | 31 | #ifndef FREERTOS_CONFIG_H 32 | #define FREERTOS_CONFIG_H 33 | 34 | /*----------------------------------------------------------- 35 | * Application specific definitions. 36 | * 37 | * These definitions should be adjusted for your particular hardware and 38 | * application requirements. 39 | * 40 | * These parameters and more are described within the 'configuration' section of the 41 | * FreeRTOS API documentation available on the FreeRTOS.org web site. 42 | * 43 | * See http://www.freertos.org/a00110.html 44 | *----------------------------------------------------------*/ 45 | 46 | /* USER CODE BEGIN Includes */ 47 | /* Section where include file can be added */ 48 | /* USER CODE END Includes */ 49 | 50 | /* Ensure definitions are only used by the compiler, and not by the assembler. */ 51 | #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) 52 | #include 53 | extern uint32_t SystemCoreClock; 54 | #endif 55 | #ifndef CMSIS_device_header 56 | #define CMSIS_device_header "stm32g4xx.h" 57 | #endif /* CMSIS_device_header */ 58 | 59 | #define configENABLE_FPU 0 60 | #define configENABLE_MPU 0 61 | 62 | #define configUSE_PREEMPTION 1 63 | #define configSUPPORT_STATIC_ALLOCATION 1 64 | #define configSUPPORT_DYNAMIC_ALLOCATION 1 65 | #define configUSE_IDLE_HOOK 0 66 | #define configUSE_TICK_HOOK 0 67 | #define configCPU_CLOCK_HZ ( SystemCoreClock ) 68 | #define configTICK_RATE_HZ ((TickType_t)1000) 69 | #define configMAX_PRIORITIES ( 56 ) 70 | #define configMINIMAL_STACK_SIZE ((uint16_t)128) 71 | #define configTOTAL_HEAP_SIZE ((size_t)3072) 72 | #define configMAX_TASK_NAME_LEN ( 16 ) 73 | #define configUSE_TRACE_FACILITY 1 74 | #define configUSE_16_BIT_TICKS 0 75 | #define configUSE_MUTEXES 1 76 | #define configQUEUE_REGISTRY_SIZE 8 77 | #define configUSE_RECURSIVE_MUTEXES 1 78 | #define configUSE_COUNTING_SEMAPHORES 1 79 | #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 80 | /* USER CODE BEGIN MESSAGE_BUFFER_LENGTH_TYPE */ 81 | /* Defaults to size_t for backward compatibility, but can be changed 82 | if lengths will always be less than the number of bytes in a size_t. */ 83 | #define configMESSAGE_BUFFER_LENGTH_TYPE size_t 84 | /* USER CODE END MESSAGE_BUFFER_LENGTH_TYPE */ 85 | 86 | /* Co-routine definitions. */ 87 | #define configUSE_CO_ROUTINES 0 88 | #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) 89 | 90 | /* Software timer definitions. */ 91 | #define configUSE_TIMERS 1 92 | #define configTIMER_TASK_PRIORITY ( 2 ) 93 | #define configTIMER_QUEUE_LENGTH 10 94 | #define configTIMER_TASK_STACK_DEPTH 256 95 | 96 | /* CMSIS-RTOS V2 flags */ 97 | #define configUSE_OS2_THREAD_SUSPEND_RESUME 1 98 | #define configUSE_OS2_THREAD_ENUMERATE 1 99 | #define configUSE_OS2_EVENTFLAGS_FROM_ISR 1 100 | #define configUSE_OS2_THREAD_FLAGS 1 101 | #define configUSE_OS2_TIMER 1 102 | #define configUSE_OS2_MUTEX 1 103 | 104 | /* Set the following definitions to 1 to include the API function, or zero 105 | to exclude the API function. */ 106 | #define INCLUDE_vTaskPrioritySet 1 107 | #define INCLUDE_uxTaskPriorityGet 1 108 | #define INCLUDE_vTaskDelete 1 109 | #define INCLUDE_vTaskCleanUpResources 0 110 | #define INCLUDE_vTaskSuspend 1 111 | #define INCLUDE_vTaskDelayUntil 1 112 | #define INCLUDE_vTaskDelay 1 113 | #define INCLUDE_xTaskGetSchedulerState 1 114 | #define INCLUDE_xTimerPendFunctionCall 1 115 | #define INCLUDE_xQueueGetMutexHolder 1 116 | #define INCLUDE_uxTaskGetStackHighWaterMark 1 117 | #define INCLUDE_xTaskGetCurrentTaskHandle 1 118 | #define INCLUDE_eTaskGetState 1 119 | 120 | /* 121 | * The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used 122 | * by the application thus the correct define need to be enabled below 123 | */ 124 | #define USE_FreeRTOS_HEAP_4 125 | 126 | /* Cortex-M specific definitions. */ 127 | #ifdef __NVIC_PRIO_BITS 128 | /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ 129 | #define configPRIO_BITS __NVIC_PRIO_BITS 130 | #else 131 | #define configPRIO_BITS 4 132 | #endif 133 | 134 | /* The lowest interrupt priority that can be used in a call to a "set priority" 135 | function. */ 136 | #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 137 | 138 | /* The highest interrupt priority that can be used by any interrupt service 139 | routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL 140 | INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER 141 | PRIORITY THAN THIS! (higher priorities are lower numeric values. */ 142 | #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 143 | 144 | /* Interrupt priorities used by the kernel port layer itself. These are generic 145 | to all Cortex-M ports, and do not rely on any particular library functions. */ 146 | #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) 147 | /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! 148 | See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ 149 | #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) 150 | 151 | /* Normal assert() semantics without relying on the provision of an assert.h 152 | header file. */ 153 | /* USER CODE BEGIN 1 */ 154 | #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} 155 | /* USER CODE END 1 */ 156 | 157 | /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS 158 | standard names. */ 159 | #define vPortSVCHandler SVC_Handler 160 | #define xPortPendSVHandler PendSV_Handler 161 | 162 | /* IMPORTANT: After 10.3.1 update, Systick_Handler comes from NVIC (if SYS timebase = systick), otherwise from cmsis_os2.c */ 163 | 164 | #define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 0 165 | 166 | /* USER CODE BEGIN Defines */ 167 | /* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */ 168 | /* USER CODE END Defines */ 169 | 170 | #endif /* FREERTOS_CONFIG_H */ 171 | -------------------------------------------------------------------------------- /firmware/Core/Inc/app.h: -------------------------------------------------------------------------------- 1 | #ifndef APP_H 2 | #define APP_H 3 | 4 | #include "main.h" 5 | 6 | #include "cmsis_os.h" 7 | 8 | #include "led.h" 9 | #include "comms.h" 10 | #include "sensors.h" 11 | #include "drive.h" 12 | #include "foc.h" 13 | #include "app_timers.h" 14 | 15 | extern ADC_HandleTypeDef hadc2; 16 | 17 | enum appState { 18 | app_state_idle, 19 | app_state_active 20 | }; 21 | 22 | extern enum appState app_state; 23 | 24 | extern int16_t current_A_mA_filtered; 25 | extern int16_t current_B_mA_filtered; 26 | extern int16_t current_C_mA_filtered; 27 | 28 | extern int16_t current_Alpha_mA; 29 | extern int16_t current_Beta_mA; 30 | 31 | extern int16_t current_Q_mA; 32 | extern int16_t current_D_mA; 33 | 34 | extern int16_t angle; 35 | extern uint8_t electrical_angle; 36 | 37 | extern int position_setpoint; 38 | 39 | /** 40 | * @brief Run during MCU init to initialise various perihperals. 41 | * 42 | * @note Order of operations 43 | * - Starts ADC 44 | * - Enables the DRV chip and calibrates amps 45 | * - Start timers 46 | * - Sets absolute encoder offset 47 | * - Zero out phase PWM 48 | * - Enable low side gates 49 | * - Start FOC interrupt 50 | */ 51 | void app_setup(); 52 | 53 | /**s 54 | * @brief RTOS task to run status led 55 | * 56 | */ 57 | void app_status_led_task(); 58 | 59 | #endif -------------------------------------------------------------------------------- /firmware/Core/Inc/app_timers.h: -------------------------------------------------------------------------------- 1 | #ifndef APP_TIMERS_H 2 | #define APP_TIMERS_H 3 | 4 | #include "main.h" 5 | 6 | extern TIM_HandleTypeDef htim7; 7 | 8 | void start_app_timers(); 9 | void app_delay_ms(uint16_t ms); 10 | 11 | #endif -------------------------------------------------------------------------------- /firmware/Core/Inc/comms.h: -------------------------------------------------------------------------------- 1 | #ifndef COMMS_H 2 | #define COMMS_H 3 | 4 | #include "main.h" 5 | #include "app.h" 6 | #include "stdbool.h" 7 | #include "comms_msgs.h" 8 | #include "foc.h" 9 | 10 | // extern enum appState; 11 | // extern enum appState app_state; 12 | 13 | extern uint16_t voltage_supply_mV; 14 | extern int16_t current_A_mA_filtered; 15 | extern int16_t current_B_mA_filtered; 16 | extern int16_t current_C_mA_filtered; 17 | 18 | extern position_control_enabled; 19 | 20 | enum canBitrate { 21 | _500Kbs = 6, 22 | _1000Kbs = 8 23 | }; 24 | 25 | extern enum canBitrate can_bitrate; 26 | 27 | extern FDCAN_HandleTypeDef hfdcan1; 28 | 29 | extern bool rx_msg_led; 30 | 31 | /** 32 | * @brief Sets up TxHeader, activates RX callback and starts CAN peripheral 33 | * 34 | */ 35 | void init_and_start_can(); 36 | 37 | /** 38 | * @brief Called when a new line of USB data is received 39 | * 40 | * @param Buf Buffer containing bytes 41 | * @param Len Length of buffer 42 | * 43 | * Buffer will fill until a newline character ('\\n') is sent through the virtual comm port 44 | */ 45 | void process_USB_rx(uint8_t* Buf, uint32_t buffer_length); 46 | 47 | void can_set_500kbs(); 48 | void can_set_1000kbs(); 49 | 50 | 51 | void handleRX(FDCAN_RxHeaderTypeDef RxHeader, uint8_t RxData[]); 52 | void handle_telemetry_RX(FDCAN_RxHeaderTypeDef RxHeader, uint8_t RxData[]); 53 | 54 | void send_slcan_string(FDCAN_RxHeaderTypeDef RxHeader, uint8_t *RxData); 55 | 56 | void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs); 57 | FDCAN_RxHeaderTypeDef convert_tx_header(FDCAN_TxHeaderTypeDef *TxHeader); 58 | 59 | #endif -------------------------------------------------------------------------------- /firmware/Core/Inc/comms_msgs.h: -------------------------------------------------------------------------------- 1 | 2 | //////////// ACTION 3 | #define ACTION_MOTOR_ENABLE_POSITION_CONTROL 50 4 | #define ACTION_MOTOR_POSITION_SETPOINT 51 5 | 6 | 7 | 8 | //////////// TELEMETRY 9 | #define TELEM_DRIVE_STATE_ID 100 10 | // DEF [drive state, drive error] 11 | 12 | #define TELEM_MOTOR_POSITION 101 13 | 14 | #define TELEM_MOTOR_PHASE_RESISTANCE 110 15 | // Motor parameters 16 | // DEF [R, R] 17 | // NAME Motor phase resistance 18 | // UNIT 19 | 20 | #define TELEM_MOTOR_CURRENTS 111 21 | // DEF [A, A, B, B, C, C] 22 | // NAME Motor currents read through shunt 23 | // UNIT mAmp 24 | // SIGNED 25 | 26 | #define TELEM_MOTOR_VOLTAGE 112 27 | // DEF [V, V] 28 | // NAME Supply voltage reading 29 | // UNIT mV -------------------------------------------------------------------------------- /firmware/Core/Inc/drive.h: -------------------------------------------------------------------------------- 1 | #ifndef DRIVE_H 2 | #define DRIVE_H 3 | 4 | #include "main.h" 5 | #include "sensors.h" 6 | #include "math.h" 7 | 8 | #include "stdbool.h" 9 | 10 | #include "cmsis_os.h" 11 | 12 | //////////// DEFINES 13 | #define MIN_MOTOR_RESISTANCE_OHM 0.1f 14 | #define MAX_MOTOR_RESISTANCE_OHM 10.0f 15 | 16 | #define MIN_SUPPLY_VOLTAGE_V 10 17 | 18 | //////////// ENUMS 19 | enum DriveError { 20 | drive_error_none, 21 | drive_error_high_resistance, 22 | drive_error_low_resistance, 23 | drive_error_no_supply 24 | }; 25 | 26 | extern enum DriveError drive_error; 27 | 28 | enum DriveState { 29 | drive_state_error, 30 | drive_state_disabled, // All phases disabled 31 | drive_state_resistance_estimation, 32 | drive_state_encoder_calibration, 33 | drive_state_idle, // Phases active but no control running 34 | drive_state_position_control 35 | }; 36 | 37 | extern enum DriveState drive_state; 38 | 39 | // If true, FOC is allowed to control motor phases 40 | extern bool foc_active; 41 | 42 | //////////// VARIABLES 43 | extern int max_motor_current_mAmps; 44 | 45 | extern int estimated_resistance_mOhms; 46 | 47 | //////////// EXTERNS 48 | extern TIM_HandleTypeDef htim1; 49 | extern TIM_HandleTypeDef htim4; 50 | extern TIM_HandleTypeDef htim6; 51 | 52 | 53 | //////////// FUNCTIONS 54 | void start_drive_timers(); 55 | 56 | // Enable DRV chip by setting ENABLE pin 57 | void enable_DRV(); 58 | // Disable DRV chip by setting ENABLE pin 59 | void disable_DRV(); 60 | 61 | /** 62 | * @brief Enable FOC loop, allowing it to apply phase voltages 63 | * 64 | */ 65 | void enable_foc_loop(); 66 | 67 | /** 68 | * @brief Disable FOC loop from applying phase voltages 69 | * and zero out phases. 70 | * 71 | */ 72 | void disable_foc_loop(); 73 | 74 | /** 75 | * @brief Estimate phase resistance by applying 76 | * a known voltage and measuring resulting phase current. 77 | * 78 | * Throws a fault if any resistance is out of line with expected. 79 | * (0.1 to 10 ohms) 80 | * 81 | * @param voltage voltage to apply during estimation 82 | * 83 | * @note 84 | * This will disable FOC during the duration of the test as it requires 85 | * direct access to phases voltages. 86 | */ 87 | void estimate_phase_resistance(float voltage); 88 | 89 | enum DriveError check_supply_voltage(); 90 | 91 | void set_duty_phase_A(uint8_t value); 92 | void set_duty_phase_B(uint8_t value); 93 | void set_duty_phase_C(uint8_t value); 94 | 95 | void set_duty_phases(uint8_t A_value, uint8_t B_value, uint8_t C_value); 96 | 97 | #endif -------------------------------------------------------------------------------- /firmware/Core/Inc/foc.h: -------------------------------------------------------------------------------- 1 | #ifndef FOC_H 2 | #define FOC_H 3 | 4 | #include "main.h" 5 | #include "drive.h" 6 | #include "sensors.h" 7 | #include "math.h" 8 | #include "trig_luts.h" 9 | #include "utils.h" 10 | 11 | 12 | extern uint16_t vmotor_mV; 13 | 14 | extern int16_t current_A_mA; 15 | extern int16_t current_B_mA; 16 | extern int16_t current_C_mA; 17 | 18 | extern int16_t current_Alpha_mA; 19 | extern int16_t current_Beta_mA; 20 | 21 | extern int16_t angle; 22 | 23 | int16_t electrical_angle_offset; 24 | 25 | /** 26 | * @brief Set target current setpoints in rotor space 27 | * 28 | * @param D_setpoint_mA D "normal current" 29 | * @param Q_setpoint_mA Q "tangent current" 30 | * 31 | * @note In normal operation, D should be set to 0, and Q set to the desired current 32 | * based on required torque. 33 | */ 34 | void set_current_setpoints(int D_setpoint_mA, int Q_setpoint_mA); 35 | 36 | /** 37 | * @brief Runs required FOC functions on TIM6 interrupt at 10KHz 38 | * 39 | */ 40 | void foc_interrupt(); 41 | 42 | /** 43 | * @brief Power invariant Clarke transform, converts from a 3-phase coordinate system to orthogonal coordinates 44 | * (with Alpha in line with phase A) 45 | * 46 | * @param A Phase A value 47 | * @param B Phase B value 48 | * @param C Phase C value 49 | * @param alpha Pointer to Alpha value to be set 50 | * @param beta Pointer to Beta value to be set 51 | */ 52 | void clarke_transform(int16_t A, int16_t B, int16_t C, int16_t *alpha, int16_t *beta); 53 | 54 | /** 55 | * @brief Park transform, converts from stator-aligned orthogonal coordinates to rotor aligned orthogonal coordinates. 56 | * D is aligned "normal" and Q is aligned "tangent". 57 | * 58 | * @param alpha Alpha value 59 | * @param beta Beta value 60 | * @param angle Electrical angle as a 8-bit integer (255 = 2pi) 61 | * @param d Pointer to D value to be set 62 | * @param q Pointer to Q value to be set 63 | */ 64 | void park_transform(int16_t alpha, int16_t beta, uint8_t angle, int16_t *d, int16_t *q); 65 | 66 | /** 67 | * @brief Inverse power invariant Clarke transform. See also `clarke_transform()` 68 | * 69 | * @param alpha Alpha value 70 | * @param beta Beta value 71 | * @param a Pointer to A-phase value to be set 72 | * @param b Pointer to A-phase value to be set 73 | * @param c Pointer to A-phase value to be set 74 | * 75 | */ 76 | void inverse_clarke_transform(int16_t alpha, int16_t beta, int16_t *a, int16_t *b, int16_t *c); 77 | 78 | /** 79 | * @brief Inverse Park transform. See also `park_transform()` 80 | * 81 | * @param d 82 | * @param q 83 | * @param angle 84 | * @param alpha 85 | * @param beta 86 | */ 87 | void inverse_park_transform(int16_t d, int16_t q, uint8_t angle, int16_t *alpha, int16_t *beta); 88 | 89 | 90 | void apply_duty_at_electrical_angle_int(uint8_t angle, uint8_t magnitude); 91 | 92 | #endif -------------------------------------------------------------------------------- /firmware/Core/Inc/led.h: -------------------------------------------------------------------------------- 1 | #ifndef LED_H 2 | #define LED_H 3 | 4 | #include "main.h" 5 | 6 | extern TIM_HandleTypeDef htim3; 7 | extern TIM_HandleTypeDef htim15; 8 | 9 | void start_led_timers(); 10 | 11 | void set_led_red_pwm(float value); 12 | void set_led_green_pwm(float value); 13 | void set_led_blue_pwm(float value); 14 | 15 | void led_hsv(float H, float S, float V); 16 | 17 | #endif -------------------------------------------------------------------------------- /firmware/Core/Inc/main.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : main.h 5 | * @brief : Header for main.c file. 6 | * This file contains the common defines of the application. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __MAIN_H 23 | #define __MAIN_H 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Includes ------------------------------------------------------------------*/ 30 | #include "stm32g4xx_hal.h" 31 | 32 | /* Private includes ----------------------------------------------------------*/ 33 | /* USER CODE BEGIN Includes */ 34 | 35 | /* USER CODE END Includes */ 36 | 37 | /* Exported types ------------------------------------------------------------*/ 38 | /* USER CODE BEGIN ET */ 39 | 40 | /* USER CODE END ET */ 41 | 42 | /* Exported constants --------------------------------------------------------*/ 43 | /* USER CODE BEGIN EC */ 44 | 45 | /* USER CODE END EC */ 46 | 47 | /* Exported macro ------------------------------------------------------------*/ 48 | /* USER CODE BEGIN EM */ 49 | 50 | /* USER CODE END EM */ 51 | 52 | void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); 53 | 54 | /* Exported functions prototypes ---------------------------------------------*/ 55 | void Error_Handler(void); 56 | 57 | /* USER CODE BEGIN EFP */ 58 | 59 | /* USER CODE END EFP */ 60 | 61 | /* Private defines -----------------------------------------------------------*/ 62 | #define DIP_1_Pin GPIO_PIN_13 63 | #define DIP_1_GPIO_Port GPIOC 64 | #define DIP_2_Pin GPIO_PIN_14 65 | #define DIP_2_GPIO_Port GPIOC 66 | #define DIP_3_Pin GPIO_PIN_15 67 | #define DIP_3_GPIO_Port GPIOC 68 | #define VM_SENSE_Pin GPIO_PIN_0 69 | #define VM_SENSE_GPIO_Port GPIOA 70 | #define LED_R_Pin GPIO_PIN_2 71 | #define LED_R_GPIO_Port GPIOA 72 | #define LED_G_Pin GPIO_PIN_3 73 | #define LED_G_GPIO_Port GPIOA 74 | #define LED_B_Pin GPIO_PIN_4 75 | #define LED_B_GPIO_Port GPIOA 76 | #define ENC_EN_Pin GPIO_PIN_0 77 | #define ENC_EN_GPIO_Port GPIOB 78 | #define IFA_Pin GPIO_PIN_1 79 | #define IFA_GPIO_Port GPIOB 80 | #define IFA_EXTI_IRQn EXTI1_IRQn 81 | #define IFB_Pin GPIO_PIN_2 82 | #define IFB_GPIO_Port GPIOB 83 | #define DRV_NFAULT_Pin GPIO_PIN_13 84 | #define DRV_NFAULT_GPIO_Port GPIOB 85 | #define DRV_EN_Pin GPIO_PIN_14 86 | #define DRV_EN_GPIO_Port GPIOB 87 | #define DRV_CAL_Pin GPIO_PIN_15 88 | #define DRV_CAL_GPIO_Port GPIOB 89 | #define INLX_Pin GPIO_PIN_6 90 | #define INLX_GPIO_Port GPIOC 91 | #define INHC_Pin GPIO_PIN_8 92 | #define INHC_GPIO_Port GPIOA 93 | #define INHB_Pin GPIO_PIN_9 94 | #define INHB_GPIO_Port GPIOA 95 | #define INHA_Pin GPIO_PIN_10 96 | #define INHA_GPIO_Port GPIOA 97 | 98 | /* USER CODE BEGIN Private defines */ 99 | 100 | /* USER CODE END Private defines */ 101 | 102 | #ifdef __cplusplus 103 | } 104 | #endif 105 | 106 | #endif /* __MAIN_H */ 107 | -------------------------------------------------------------------------------- /firmware/Core/Inc/sensors.h: -------------------------------------------------------------------------------- 1 | #ifndef SENSORS_H 2 | #define SENSORS_H 3 | 4 | #include "main.h" 5 | #include "stdbool.h" 6 | 7 | #define AMP_GAIN 40.0f 8 | #define SHUNT_VALUE_R 0.002f 9 | #define ADC_MIDPOINT 2048.0f 10 | #define ADC_MAX 4096.0f 11 | 12 | extern ADC_HandleTypeDef hadc1; 13 | extern ADC_HandleTypeDef hadc2; 14 | 15 | extern uint16_t adc1_dma[2]; 16 | extern uint16_t adc2_dma[3]; 17 | 18 | extern uint16_t phase_resistance_mOhm[3]; 19 | 20 | extern uint16_t v_motor_mv; 21 | 22 | /** 23 | * @brief Current sense 0 offset 24 | * 25 | */ 26 | extern uint32_t adc2_calib_offset[3]; 27 | 28 | /** 29 | * @brief Current sense in AMPs 30 | * Call update_current_sense to update 31 | */ 32 | extern float current_sense[3]; 33 | extern float alpha_current; 34 | extern float beta_current; 35 | 36 | extern int enc_angle_int; 37 | extern uint16_t enc_angle_uint12; 38 | 39 | /** 40 | * @brief 41 | * 42 | */ 43 | void encoder_ISR(); 44 | 45 | /** 46 | * @brief Set absolute encoder offset. 47 | * Sets the absolute encoder offset by power cycling IC then reading out startup pulses 48 | */ 49 | void set_encoder_absolute_offset(); 50 | 51 | /** 52 | * @brief Sets up DMA on ADC channels 2 and 3 53 | * 54 | * 55 | */ 56 | void start_ADC(); 57 | 58 | /** 59 | * @brief Runs calibration on the DRV current shunt amps. 60 | * Starts by running DRV internal calibration, then sets an external offset 61 | * 62 | */ 63 | void calibrate_DRV_amps(); 64 | 65 | /** 66 | * @brief Re-calculate current sense (in amps) 67 | * Uses floating-point so ideally shouldn't be used in the FOC loop 68 | * 69 | */ 70 | void update_current_sense(); 71 | 72 | float get_vmotor(); 73 | 74 | #endif -------------------------------------------------------------------------------- /firmware/Core/Inc/stm32g4xx_it.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file stm32g4xx_it.h 5 | * @brief This file contains the headers of the interrupt handlers. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2023 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file 13 | * in the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | * 16 | ****************************************************************************** 17 | */ 18 | /* USER CODE END Header */ 19 | 20 | /* Define to prevent recursive inclusion -------------------------------------*/ 21 | #ifndef __STM32G4xx_IT_H 22 | #define __STM32G4xx_IT_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /* Private includes ----------------------------------------------------------*/ 29 | /* USER CODE BEGIN Includes */ 30 | 31 | /* USER CODE END Includes */ 32 | 33 | /* Exported types ------------------------------------------------------------*/ 34 | /* USER CODE BEGIN ET */ 35 | 36 | /* USER CODE END ET */ 37 | 38 | /* Exported constants --------------------------------------------------------*/ 39 | /* USER CODE BEGIN EC */ 40 | 41 | /* USER CODE END EC */ 42 | 43 | /* Exported macro ------------------------------------------------------------*/ 44 | /* USER CODE BEGIN EM */ 45 | 46 | /* USER CODE END EM */ 47 | 48 | /* Exported functions prototypes ---------------------------------------------*/ 49 | void NMI_Handler(void); 50 | void HardFault_Handler(void); 51 | void MemManage_Handler(void); 52 | void BusFault_Handler(void); 53 | void UsageFault_Handler(void); 54 | void DebugMon_Handler(void); 55 | void EXTI1_IRQHandler(void); 56 | void DMA1_Channel1_IRQHandler(void); 57 | void DMA1_Channel2_IRQHandler(void); 58 | void ADC1_2_IRQHandler(void); 59 | void USB_LP_IRQHandler(void); 60 | void FDCAN1_IT0_IRQHandler(void); 61 | void TIM1_TRG_COM_TIM17_IRQHandler(void); 62 | void TIM2_IRQHandler(void); 63 | void TIM6_DAC_IRQHandler(void); 64 | /* USER CODE BEGIN EFP */ 65 | 66 | /* USER CODE END EFP */ 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | #endif /* __STM32G4xx_IT_H */ 73 | -------------------------------------------------------------------------------- /firmware/Core/Inc/trig_luts.h: -------------------------------------------------------------------------------- 1 | #ifndef TRIG_LUTS 2 | #define TRIG_LUTS 3 | 4 | #define LUT_LENGTH 256 5 | 6 | #include "main.h" 7 | 8 | uint8_t mult_sin_lut_uint8(uint8_t value, uint8_t position); 9 | int16_t mult_sin_lut_int16(uint8_t position, int16_t value); 10 | 11 | #endif -------------------------------------------------------------------------------- /firmware/Core/Inc/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | 4 | #include "main.h" 5 | #include "stdbool.h" 6 | 7 | // Returns the minimum of 3 provided int16s 8 | int16_t int16_min3(int16_t a, int16_t b, int16_t c); 9 | 10 | // Returns an integer bounded by a min and max 11 | int bound(int value, int min, int max); 12 | 13 | // Bounds an integer between a min and max, returns true if bounded 14 | bool enforce_bound(int *value, int min, int max); 15 | 16 | #endif -------------------------------------------------------------------------------- /firmware/Core/Src/app.c: -------------------------------------------------------------------------------- 1 | #include "app.h" 2 | 3 | enum appState app_state = app_state_idle; 4 | 5 | void app_setup(){ 6 | // Start and calibrate analog 7 | // (at beginning since calibration works best with ) 8 | start_ADC(); 9 | 10 | // Enable DRV 11 | enable_DRV(); 12 | calibrate_DRV_amps(); 13 | 14 | // Start timers 15 | // TODO: Does this make sense 16 | start_led_timers(); 17 | start_drive_timers(); 18 | start_app_timers(); 19 | 20 | // Start comms 21 | init_and_start_can(); 22 | 23 | // Set encoder offset 24 | set_encoder_absolute_offset(); 25 | 26 | // Setup DRIVE 27 | set_duty_phases(0, 0, 0); 28 | // Enable low side gates 29 | // TODO: Add this into a "drive enable/disable" function 30 | HAL_GPIO_WritePin(INLX_GPIO_Port, INLX_Pin, 1); 31 | 32 | // 10kHz motor commutation interrupt 33 | // TODO: Add this back into drive timers? 34 | // Can't quite remember why it's here 35 | HAL_TIM_Base_Start_IT(&htim6); 36 | } 37 | 38 | 39 | int led_clock = 0; 40 | char str[50]; 41 | 42 | void app_status_led_task(){ 43 | 44 | // estimate_phase_resistance(5.0); 45 | 46 | led_clock += 1; 47 | switch (app_state){ 48 | case app_state_idle: 49 | // led_hsv(150.0f, 1.0f, sin(led_clock / 30.0f) * 0.2f + 0.2f); 50 | led_hsv((enc_angle_int)/(4096.0f / 360.0f) + 10000.0f, 1.0f, sin(led_clock / 100.0f) * 0.3f + 0.4f); 51 | break; 52 | case app_state_active: 53 | if(rx_msg_led){ 54 | led_hsv(led_clock/5.0f, 0.9f, 1.0f); 55 | rx_msg_led = false; 56 | }else if(can_bitrate == _500Kbs){ 57 | led_hsv(led_clock/5.0f, 0.9f, 0.5f); 58 | }else if(can_bitrate == _1000Kbs){ 59 | led_hsv(led_clock/5.0f, 0.9f, 0.5f); 60 | } 61 | break; 62 | } 63 | 64 | // sprintf(str, "%d %d %d %d %d %d %d %d\r", electrical_angle, current_A_mA_filtered, current_B_mA_filtered, current_C_mA_filtered, current_Alpha_mA, current_Beta_mA, current_D_mA, current_Q_mA); 65 | // sprintf(str, "%+05d %+05d\r", enc_angle_int, position_setpoint); 66 | // sprintf(str, "%+05d %+05d\r", electrical_angle, (uint8_t) position_setpoint); 67 | // sprintf(str, "%+05d %+05d %+05d\r", (uint8_t)angle, current_Alpha_mA, current_Beta_mA); 68 | // sprintf(str, "%+05d %+05d\r", current_D_mA, current_Q_mA); 69 | // CDC_Transmit_FS(str, strlen(str)); 70 | 71 | // position_setpoint = sin(led_clock / 500.0f) * 4000.0f; 72 | // position_setpoint = 0; 73 | 74 | // position_setpoint = (int)(sin(led_clock / 5000.0f) * 8000.0f) 75 | enable_foc_loop(); 76 | // position_setpoint = led_clock; 77 | 78 | // apply_duty_at_electrical_angle_int(position_setpoint, 30); 79 | // position_setpoint += 1; 80 | 81 | // set_duty_phase_A(0); 82 | // set_duty_phase_B(0); 83 | // set_duty_phase_C(0); 84 | // // angle += 1; 85 | 86 | osDelay(5); 87 | // angle += 1; 88 | } -------------------------------------------------------------------------------- /firmware/Core/Src/app_freertos.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * File Name : app_freertos.c 5 | * Description : Code for freertos applications 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2023 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file 13 | * in the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | * 16 | ****************************************************************************** 17 | */ 18 | /* USER CODE END Header */ 19 | 20 | /* Includes ------------------------------------------------------------------*/ 21 | #include "FreeRTOS.h" 22 | #include "task.h" 23 | #include "main.h" 24 | 25 | /* Private includes ----------------------------------------------------------*/ 26 | /* USER CODE BEGIN Includes */ 27 | 28 | /* USER CODE END Includes */ 29 | 30 | /* Private typedef -----------------------------------------------------------*/ 31 | /* USER CODE BEGIN PTD */ 32 | 33 | /* USER CODE END PTD */ 34 | 35 | /* Private define ------------------------------------------------------------*/ 36 | /* USER CODE BEGIN PD */ 37 | 38 | /* USER CODE END PD */ 39 | 40 | /* Private macro -------------------------------------------------------------*/ 41 | /* USER CODE BEGIN PM */ 42 | 43 | /* USER CODE END PM */ 44 | 45 | /* Private variables ---------------------------------------------------------*/ 46 | /* USER CODE BEGIN Variables */ 47 | 48 | /* USER CODE END Variables */ 49 | 50 | /* Private function prototypes -----------------------------------------------*/ 51 | /* USER CODE BEGIN FunctionPrototypes */ 52 | 53 | /* USER CODE END FunctionPrototypes */ 54 | 55 | /* Private application code --------------------------------------------------*/ 56 | /* USER CODE BEGIN Application */ 57 | 58 | /* USER CODE END Application */ 59 | 60 | -------------------------------------------------------------------------------- /firmware/Core/Src/app_timers.c: -------------------------------------------------------------------------------- 1 | #include "app_timers.h" 2 | 3 | void start_app_timers(){ 4 | HAL_TIM_Base_Start(&htim7); 5 | } 6 | 7 | void app_delay_ms(uint16_t ms){ 8 | __HAL_TIM_SET_COUNTER(&htim7, 0); // set the counter value a 0 9 | volatile int test = __HAL_TIM_GET_COUNTER(&htim7); 10 | while (__HAL_TIM_GET_COUNTER(&htim7) < ms * 10){ 11 | volatile int test = __HAL_TIM_GET_COUNTER(&htim7); 12 | }; 13 | } -------------------------------------------------------------------------------- /firmware/Core/Src/drive.c: -------------------------------------------------------------------------------- 1 | #include "drive.h" 2 | 3 | enum DriveError drive_error = drive_error_none; 4 | enum DriveState drive_state = drive_state_idle; 5 | 6 | // If true, FOC is allowed to control motor phases 7 | bool foc_active = false; 8 | 9 | //////////// VARIABLES 10 | int max_motor_current_mAmps = 1000; 11 | 12 | int estimated_resistance_mOhms = -1; 13 | 14 | 15 | 16 | 17 | 18 | 19 | void start_drive_timers(){ 20 | HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); 21 | HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2); 22 | HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3); 23 | } 24 | 25 | void enable_DRV(){ 26 | HAL_GPIO_WritePin(DRV_EN_GPIO_Port, DRV_EN_Pin, 1); 27 | } 28 | 29 | void disable_DRV(){ 30 | HAL_GPIO_WritePin(DRV_EN_GPIO_Port, DRV_EN_Pin, 0); 31 | } 32 | 33 | void enable_foc_loop(){ 34 | foc_active = true; 35 | } 36 | 37 | void disable_foc_loop(){ 38 | foc_active = false; 39 | set_duty_phases(0, 0, 0); 40 | } 41 | 42 | 43 | 44 | 45 | 46 | // Currently only checks phase A as that amp seems to be the most accurate 47 | void estimate_phase_resistance(float voltage){ 48 | if(drive_state != drive_state_idle) { 49 | return; 50 | } 51 | 52 | // Verify we have motor supply voltage 53 | if(check_supply_voltage() != drive_error_none){ 54 | return; 55 | } 56 | 57 | disable_foc_loop(); 58 | drive_state = drive_state_resistance_estimation; 59 | 60 | // Calculate required duty cycle for voltage 61 | float input_voltage = get_vmotor(); 62 | float desired_voltage = voltage; 63 | int duty = (int)((desired_voltage / input_voltage) * 256); 64 | 65 | // Apply voltage 66 | set_duty_phases(0, duty, 0); 67 | osDelay(50); 68 | 69 | // Sample current 70 | int current_adc = 0; 71 | const int NUM_SAMPLES = 10; 72 | for(int i = 0; i < 10; i++){ 73 | current_adc += adc2_dma[0]; 74 | osDelay(1); 75 | } 76 | 77 | current_adc = current_adc / NUM_SAMPLES; 78 | 79 | // Reset phases 80 | set_duty_phases(0, 0, 0); 81 | 82 | float measured_shunt_voltage = ((current_adc / 4096.0 - 0.5) * 2.8f) / 40.0f; 83 | float measured_shunt_current = fabs(measured_shunt_voltage / 0.002f); 84 | 85 | // Calculate resistance 86 | estimated_resistance_mOhms = (int) (desired_voltage / measured_shunt_current * 1000); 87 | 88 | 89 | 90 | // Check if resistance is within expected values 91 | if(estimated_resistance_mOhms > MAX_MOTOR_RESISTANCE_OHM * 1000){ 92 | drive_state = drive_state_error; 93 | drive_error = drive_error_high_resistance; 94 | return; 95 | }else if(estimated_resistance_mOhms < MIN_MOTOR_RESISTANCE_OHM * 1000){ 96 | drive_state = drive_state_error; 97 | drive_error = drive_error_high_resistance; 98 | return; 99 | } else { 100 | drive_state = drive_state_idle; 101 | enable_foc_loop(); 102 | } 103 | } 104 | 105 | 106 | 107 | 108 | 109 | enum DriveError check_supply_voltage() { 110 | if(get_vmotor() < MIN_SUPPLY_VOLTAGE_V){ 111 | drive_error = drive_error_no_supply; 112 | drive_state = drive_state_error; 113 | } 114 | 115 | return drive_error; 116 | } 117 | 118 | void set_duty_phase_A(uint8_t value){ 119 | TIM1->CCR3 = value; 120 | } 121 | 122 | void set_duty_phase_B(uint8_t value){ 123 | TIM1->CCR2 = value; 124 | } 125 | 126 | void set_duty_phase_C(uint8_t value){ 127 | TIM1->CCR1 = value; 128 | } 129 | 130 | void set_duty_phases(uint8_t A_value, uint8_t B_value, uint8_t C_value){ 131 | set_duty_phase_A(A_value); 132 | set_duty_phase_B(B_value); 133 | set_duty_phase_C(C_value); 134 | } -------------------------------------------------------------------------------- /firmware/Core/Src/foc.c: -------------------------------------------------------------------------------- 1 | #include "foc.h" 2 | 3 | #define SQRT_1_2 0.7071067812f 4 | #define SQRT_2_3 0.8164965809f 5 | #define SQRT_3 1.7320508076f 6 | 7 | uint16_t voltage_supply_mV; 8 | 9 | 10 | bool position_control_enabled = false; 11 | 12 | // Current Variables 13 | int position_setpoint_filtered = 0; 14 | int current_setpoint_limit_mA = 1000; 15 | int current_Q_setpoint_mA = 0; 16 | int current_D_setpoint_mA = 0; 17 | 18 | int16_t current_A_mA = 0; 19 | int16_t current_B_mA = 0; 20 | int16_t current_C_mA = 0; 21 | 22 | int16_t current_A_offset_mA = 0; 23 | int16_t current_C_offset_mA = -51; 24 | 25 | int16_t current_A_mA_filtered = 0; 26 | int16_t current_B_mA_filtered = 0; 27 | int16_t current_C_mA_filtered = 0; 28 | 29 | int16_t current_Alpha_mA = 0; 30 | int16_t current_Beta_mA = 0; 31 | 32 | int16_t current_D_mA = 0; 33 | int16_t current_Q_mA = 0; 34 | 35 | 36 | // Voltage Variables 37 | int8_t maximum_duty = 200; 38 | 39 | int16_t voltage_D_mV = 0; 40 | int16_t voltage_Q_mV = 0; 41 | 42 | int16_t voltage_Alpha_mV = 0; 43 | int16_t voltage_Beta_mV = 0; 44 | 45 | int16_t voltage_a_mV = 0; 46 | int16_t voltage_b_mV = 0; 47 | int16_t voltage_c_mV = 0; 48 | 49 | // Gains 50 | // TODO: Choose this based on motor resistance and inductance 51 | float current_P_gain = 0.02f; 52 | 53 | // Angle 54 | uint8_t electrical_angle = 0; 55 | uint8_t electrical_angle_offset = -39; 56 | 57 | int position_setpoint = 0; 58 | 59 | void set_current_setpoints(int D_setpoint_mA, int Q_setpoint_mA){ 60 | current_Q_setpoint_mA = Q_setpoint_mA; 61 | current_D_setpoint_mA = D_setpoint_mA; 62 | } 63 | 64 | void foc_interrupt(){ 65 | // Calculate electrical angle as a uint8 66 | // 0 is aligned with phase A 67 | // 255 is just before wraparound 68 | electrical_angle = enc_angle_int % (4096 / 8) / 2 - electrical_angle_offset; 69 | 70 | // Calculate motor voltage 71 | voltage_supply_mV = adc1_dma[0] * 13; 72 | 73 | // Calculate motor currents and transform them 74 | // 9 is a magic number 75 | // TODO: Document 9 76 | current_A_mA = (adc2_dma[0] - 2048 + current_A_offset_mA) * 9; 77 | current_C_mA = (adc2_dma[1] - 2048 - current_C_offset_mA) * 9; 78 | current_B_mA = - (current_A_mA + current_C_mA); 79 | 80 | // Perform an IIR filter on current to cut down on noise and injected vibrations 81 | current_A_mA_filtered = current_A_mA_filtered * 0.9f + current_A_mA * 0.1f; 82 | current_B_mA_filtered = current_B_mA_filtered * 0.9f + current_B_mA * 0.1f; 83 | current_C_mA_filtered = current_C_mA_filtered * 0.9f + current_C_mA * 0.1f; 84 | 85 | // Perform clarke and park transform to get motor current in orthogonal rotor-centric coordinates 86 | clarke_transform(current_A_mA_filtered, current_B_mA_filtered, current_C_mA_filtered, ¤t_Alpha_mA, ¤t_Beta_mA); 87 | park_transform(current_Alpha_mA, current_Beta_mA, electrical_angle, ¤t_D_mA, ¤t_Q_mA); 88 | 89 | // Generate current setpoint 90 | // TODO: Split this out into another timer interrupt 91 | 92 | if(position_control_enabled){ 93 | position_setpoint_filtered = 0.99f * position_setpoint_filtered + position_setpoint * 0.01f; 94 | current_Q_setpoint_mA = 0.0f * current_Q_setpoint_mA + ((position_setpoint_filtered - enc_angle_int) * 20.0f) * 1.0f; 95 | } else { 96 | current_Q_setpoint_mA = 0; 97 | } 98 | 99 | current_setpoint_limit_mA = 10000; // 1A current setpoint for testing 100 | 101 | // torque_setpoint = (position_setpoint - enc_angle_int) * 1.0f 102 | // position_setpoint = bound( (int16_t) (position_setpoint - enc_angle_int) * 1.0f, -current_setpoint_limit_mA, current_setpoint_limit_mA); 103 | // current_Q_setpoint_mA = -1000; 104 | // Enforce limits on current 105 | current_Q_setpoint_mA = bound(current_Q_setpoint_mA, -current_setpoint_limit_mA, current_setpoint_limit_mA); 106 | 107 | // Q current P loop 108 | // TODO: Add an integral term? 109 | voltage_Q_mV = (current_Q_mA - current_Q_setpoint_mA) * current_P_gain; 110 | // voltage_Q_mV = -current_Q_setpoint_mA * 0.01f; 111 | // voltage_Q_mV = 20; 112 | voltage_Q_mV = (int16_t) bound(voltage_Q_mV, -200, 200); 113 | // D current P loop 114 | voltage_D_mV = -(current_D_mA - current_D_setpoint_mA) * current_P_gain; 115 | // voltage_D_mV = 0; 116 | voltage_D_mV = (int16_t) bound(voltage_D_mV, -200, 200); 117 | 118 | // Perform inverse park and clarke transform to convert from rotor-centric voltage into phase voltages 119 | inverse_park_transform(voltage_D_mV, voltage_Q_mV, electrical_angle, &voltage_Alpha_mV, &voltage_Beta_mV); 120 | inverse_clarke_transform(voltage_Alpha_mV, voltage_Beta_mV, &voltage_a_mV, &voltage_b_mV, &voltage_c_mV); 121 | // Find minimum voltage to offset phase voltages to be all positive 122 | // Might be worth experimenting with centering phases around V_supply/2 to avoid this 123 | // there might be additional consequences 124 | 125 | int16_t min_voltage_mV = int16_min3(voltage_a_mV, voltage_b_mV, voltage_c_mV); 126 | 127 | 128 | // If FOC is enabled, set voltages 129 | if(foc_active){ 130 | // TODO, convert to setting actual voltages instead of duty cycle 131 | set_duty_phases(voltage_a_mV - min_voltage_mV, voltage_b_mV - min_voltage_mV, voltage_c_mV - min_voltage_mV); 132 | } 133 | } 134 | 135 | void clarke_transform(int16_t A, int16_t B, int16_t C, int16_t *alpha, int16_t *beta){ 136 | *alpha = (int16_t) ( SQRT_2_3 * (1 * A - B / 2 - C / 2 ) ); 137 | *beta = (int16_t) ( SQRT_2_3 * (0 * A + SQRT_3 * B / 2 - SQRT_3 * C / 2) ); 138 | } 139 | 140 | void park_transform(int16_t alpha, int16_t beta, uint8_t angle, int16_t *d, int16_t *q){ 141 | *d = mult_sin_lut_int16(angle + 64, alpha) + mult_sin_lut_int16(angle, beta); 142 | *q = mult_sin_lut_int16(angle + 64, beta) - mult_sin_lut_int16(angle, alpha); 143 | } 144 | 145 | void inverse_clarke_transform(int16_t alpha, int16_t beta, int16_t *a, int16_t *b, int16_t *c){ 146 | *a = SQRT_2_3 * ( 1 * alpha ); 147 | *b = SQRT_2_3 * ( - alpha / 2.0f + SQRT_3 * beta / 2.0f); 148 | *c = SQRT_2_3 * ( - alpha / 2.0f - SQRT_3 * beta / 2.0f); 149 | } 150 | 151 | void inverse_park_transform(int16_t d, int16_t q, uint8_t angle, int16_t *alpha, int16_t *beta){ 152 | *alpha = mult_sin_lut_int16(angle + 64, d) + mult_sin_lut_int16(angle, q); 153 | *beta = mult_sin_lut_int16(angle + 64, q) - mult_sin_lut_int16(angle, d); 154 | } 155 | 156 | 157 | 158 | 159 | /////////// LEGACY /////////// 160 | void apply_duty_at_electrical_angle_int(uint8_t angle, uint8_t magnitude){ 161 | angle = (angle + (1.0 / 4.0) * 256); 162 | 163 | uint8_t A_value = mult_sin_lut_uint8((uint8_t) (angle + (0.0 / 3.0) * 256), magnitude); 164 | uint8_t B_value = mult_sin_lut_uint8((uint8_t) (angle + (1.0 / 3.0) * 256), magnitude); 165 | uint8_t C_value = mult_sin_lut_uint8((uint8_t) (angle + (2.0 / 3.0) * 256), magnitude); 166 | 167 | set_duty_phase_A(A_value); 168 | set_duty_phase_B(B_value); 169 | set_duty_phase_C(C_value); 170 | } 171 | 172 | void spin_electrical_rads_sin(float revs, int calibration_voltage){ 173 | for(int i = 0; i<=255; i++){ 174 | // apply_voltage_at_electrical_angle((i / 100.0f) * rads, calibration_voltage); 175 | apply_voltage_at_electrical_angle_int((uint8_t) (int) (i * revs) % 254, calibration_voltage); 176 | osDelay(5); 177 | } 178 | } 179 | 180 | void spin_electrical_rev_forward(int calibration_voltage){ 181 | for(int i = 0; i<=255; i++){ 182 | // apply_voltage_at_electrical_angle((i / 100.0f) * rads, calibration_voltage); 183 | apply_voltage_at_electrical_angle_int(i, calibration_voltage); 184 | osDelay(5); 185 | } 186 | } 187 | 188 | 189 | void spin_electrical_rev_backward(int calibration_voltage){ 190 | for(int i = 0; i<=255; i++){ 191 | // apply_voltage_at_electrical_angle((i / 100.0f) * rads, calibration_voltage); 192 | apply_voltage_at_electrical_angle_int(255 - i, calibration_voltage); 193 | osDelay(5); 194 | } 195 | } -------------------------------------------------------------------------------- /firmware/Core/Src/led.c: -------------------------------------------------------------------------------- 1 | #include "led.h" 2 | 3 | void start_led_timers(){ 4 | // LED 5 | HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2); 6 | HAL_TIM_PWM_Start(&htim15, TIM_CHANNEL_1); 7 | HAL_TIM_PWM_Start(&htim15, TIM_CHANNEL_2); 8 | } 9 | 10 | 11 | const uint16_t R_LED_MAX = 200; 12 | void set_led_red_pwm(float value){ 13 | TIM15->CCR1 = (value * R_LED_MAX); 14 | } 15 | 16 | const uint16_t G_LED_MAX = 70; 17 | void set_led_green_pwm(float value){ 18 | TIM15->CCR2 = (value * G_LED_MAX); 19 | } 20 | 21 | const uint16_t B_LED_MAX = 70; 22 | void set_led_blue_pwm(float value){ 23 | TIM3->CCR2 = (value * B_LED_MAX); 24 | } 25 | 26 | void led_hsv(float H, float S, float V){ 27 | 28 | // Log dimming curve 29 | if(V < 0){ 30 | V = 0; 31 | } 32 | V = V*V; 33 | 34 | float C = V * S; 35 | float H_prime = fmod(H, 360) / 60.0f; 36 | // volatile float mod_test = fabs((float)fmod(H_prime, 2) - 1.0f; 37 | float X = C * (1.0f - fabs( fmod(H_prime, 2.0f) - 1.0f)); 38 | 39 | float r = 0; 40 | float g = 0; 41 | float b = 0; 42 | 43 | if(0 <= H_prime && H_prime < 1){ 44 | r = C; 45 | g = X; 46 | }else if(1 <= H_prime && H_prime < 2){ 47 | r = X; 48 | g = C; 49 | }else if(2 <= H_prime && H_prime < 3){ 50 | g = C; 51 | b = X; 52 | }else if(3 <= H_prime && H_prime < 4){ 53 | g = X; 54 | b = C; 55 | }else if(4 <= H_prime && H_prime < 5){ 56 | r = X; 57 | b = C; 58 | }else if(5 <= H_prime && H_prime < 6){ 59 | r = C; 60 | b = X; 61 | } 62 | 63 | float m = V - C; 64 | 65 | set_led_red_pwm(r + m); 66 | set_led_green_pwm(g + m); 67 | set_led_blue_pwm(b + m); 68 | } -------------------------------------------------------------------------------- /firmware/Core/Src/sensors.c: -------------------------------------------------------------------------------- 1 | #include "sensors.h" 2 | #include "app_timers.h" 3 | 4 | uint16_t adc1_dma[2]; 5 | uint16_t adc2_dma[3]; 6 | uint32_t adc2_calib_offset[3]; 7 | 8 | float current_sense[3]; 9 | float alpha_current; 10 | float beta_current; 11 | 12 | uint16_t phase_resistance[3]; // Phase resistance in milliohms 13 | 14 | uint16_t v_motor_mv; // Motor input voltage in millivolts 15 | 16 | int enc_angle_int; 17 | uint16_t enc_angle_uint12; 18 | 19 | bool start_up_pulses = false; 20 | uint16_t start_up_pulse_count = 0; 21 | 22 | void encoder_ISR(){ 23 | if(start_up_pulses || HAL_GPIO_ReadPin(IFB_GPIO_Port, IFB_Pin)){ 24 | enc_angle_int ++; 25 | }else{ 26 | enc_angle_int --; 27 | } 28 | } 29 | 30 | void set_encoder_absolute_offset(){ 31 | // TODO: This is very very hacky and I do not like it 32 | 33 | // GET PULSE COUNT 34 | // Disable magnetic encoder 35 | start_up_pulses = true; 36 | HAL_GPIO_WritePin(ENC_EN_GPIO_Port, ENC_EN_Pin, 1); 37 | app_delay_ms(10); 38 | 39 | // Reset angle 40 | enc_angle_int = 0; 41 | // Enable magnetic encoder 42 | HAL_GPIO_WritePin(ENC_EN_GPIO_Port, ENC_EN_Pin, 0); 43 | // app_delay_ms(10); 44 | HAL_Delay(10); 45 | start_up_pulse_count = enc_angle_int; 46 | 47 | // FIND DIRECTION 48 | start_up_pulses = false; 49 | HAL_GPIO_WritePin(ENC_EN_GPIO_Port, ENC_EN_Pin, 1); 50 | app_delay_ms(10); 51 | // Reset angle 52 | enc_angle_int = 0; 53 | // Enable magnetic encoder 54 | HAL_GPIO_WritePin(ENC_EN_GPIO_Port, ENC_EN_Pin, 0); 55 | app_delay_ms(10); 56 | // Adjust startup pulse direction 57 | if(enc_angle_int < 0){ 58 | enc_angle_int = start_up_pulse_count; 59 | }else{ 60 | enc_angle_int = -start_up_pulse_count; 61 | } 62 | 63 | 64 | } 65 | 66 | // Calibrate provided ADC 67 | // TODO: Handle errors 68 | void calibrate_ADC(ADC_HandleTypeDef *hadc){ 69 | if(HAL_ADCEx_Calibration_Start(hadc, ADC_SINGLE_ENDED) != HAL_OK){ 70 | Error_Handler(); 71 | } 72 | } 73 | 74 | void start_ADC(){ 75 | 76 | // Calibrate and start adc1 DMA (vmot + temp) 77 | calibrate_ADC(&hadc1); 78 | HAL_ADC_Start_DMA(&hadc1, adc1_dma, 2); 79 | 80 | // Calibrate and start adc2 DMA (phase current shunts) 81 | calibrate_ADC(&hadc2); 82 | HAL_ADC_Start_DMA(&hadc2, adc2_dma, 3); 83 | } 84 | 85 | // Update and get v motor 86 | float get_vmotor(){ 87 | // float R1 = 100.0f; // kOhms 88 | // float R2 = 6.8f; // KOhms 89 | // float adc_constant = 3.3f / 4096.0f * 1.00f; 90 | // float adc_v = adc1_dma[0] * adc_constant; 91 | // // volatile float voltage_divider_const = 92 | // v_motor_mv = (adc_v * ((R1 + R2) / R2)); 93 | volatile float v_motor = (adc1_dma[0]*0.000806f / 0.0637f)*1.0f; 94 | return v_motor; 95 | } 96 | 97 | void calibrate_DRV_amps(){ 98 | // Perform DRV amp calibration 99 | HAL_GPIO_WritePin(DRV_CAL_GPIO_Port, DRV_CAL_Pin, 0); 100 | HAL_Delay(2); 101 | HAL_GPIO_WritePin(DRV_CAL_GPIO_Port, DRV_CAL_Pin, 1); 102 | // Wait for internal calibration 103 | HAL_Delay(10); 104 | 105 | // Perform external calibration 106 | // TODO: Have average over a set of samples 107 | // adc2_calib_offset[0] = 0; 108 | // adc2_calib_offset[1] = 0; 109 | // adc2_calib_offset[2] = 0; 110 | 111 | // Disable calibration 112 | HAL_GPIO_WritePin(DRV_CAL_GPIO_Port, DRV_CAL_Pin, 0); 113 | 114 | // int num_samples = 200; 115 | // for(int i = 0; i < num_samples; i++){ 116 | // adc2_calib_offset[0] += adc2_dma[0]; 117 | // adc2_calib_offset[1] += adc2_dma[1]; 118 | // adc2_calib_offset[2] += adc2_dma[0]; 119 | // HAL_Delay(1); 120 | // } 121 | // adc2_calib_offset[0] /= num_samples; 122 | // adc2_calib_offset[1] /= num_samples; 123 | // adc2_calib_offset[2] /= num_samples; 124 | } 125 | 126 | void update_current_sense(){ 127 | float filter_constant = 0.005f; 128 | // TODO: Set up proper phase numbering 129 | // current_sense[0] = (current_sense[0]) * (1 - filter_constant) + (((((int)adc2_dma[0] - (int)adc2_calib_offset[0]) / ADC_MAX) * 3.3f) / (AMP_GAIN * SHUNT_VALUE_R)) * filter_constant; 130 | // current_sense[1] = (current_sense[1]) * (1 - filter_constant) + (((((int)adc2_dma[1] - (int)adc2_calib_offset[1]) / ADC_MAX) * 3.3f) / (AMP_GAIN * SHUNT_VALUE_R)) * filter_constant; 131 | // // current_sense[2] = -current_sense[0] - current_sense[1]; 132 | // current_sense[2] = (current_sense[2]) * (1 - filter_constant) + (((((int)adc2_dma[2] - (int)adc2_calib_offset[2]) / ADC_MAX) * 3.3f) / (AMP_GAIN * SHUNT_VALUE_R)) * filter_constant; 133 | 134 | current_sense[0] = (current_sense[0]) * (1 - filter_constant) + (((((int)(adc2_calib_offset[0]) - (int)(adc2_dma[0])) / ADC_MAX) * 3.3f*1.00f) / (AMP_GAIN * SHUNT_VALUE_R)) * filter_constant; 135 | current_sense[1] = (current_sense[1]) * (1 - filter_constant) + (((((int)(adc2_calib_offset[1]) - (int)(adc2_dma[1])) / ADC_MAX) * 3.3f*1.00f) / (AMP_GAIN * SHUNT_VALUE_R)) * filter_constant; 136 | current_sense[2] = -current_sense[0] - current_sense[1]; 137 | // current_sense[2] = (current_sense[2]) * (1 - filter_constant) + (((((int)adc2_calib_offset[2] - (int)adc2_dma[2]) / ADC_MAX) * 3.3f*1.00f / (AMP_GAIN))) * filter_constant; 138 | 139 | 140 | // alpha_current = sqrtf(2.0f/3.0f) * (1.0f * current_sense[0] - 0.5f * current_sense[1] - 0.5f * current_sense[2]); 141 | // beta_current = sqrtf(2.0f/3.0f) * (0.0f * current_sense[0] + sqrtf(3.0f)/2.0f * current_sense[1] - sqrtf(3.0f)/2.0f * current_sense[2]); 142 | // current_sense[0] = (current_sense[0]) * (1.0f - filter_constant) + adc2_dma[0] * filter_constant; 143 | // current_sense[1] = (current_sense[1]) * (1.0f - filter_constant) + adc2_dma[1] * filter_constant; 144 | // current_sense[2] = (current_sense[2]) * (1.0f - filter_constant) + adc2_dma[2] * filter_constant; 145 | } -------------------------------------------------------------------------------- /firmware/Core/Src/stm32g4xx_hal_timebase_tim.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file stm32g4xx_hal_timebase_tim.c 5 | * @brief HAL time base based on the hardware TIM. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2023 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file 13 | * in the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | * 16 | ****************************************************************************** 17 | */ 18 | /* USER CODE END Header */ 19 | 20 | /* Includes ------------------------------------------------------------------*/ 21 | #include "stm32g4xx_hal.h" 22 | #include "stm32g4xx_hal_tim.h" 23 | 24 | /* Private typedef -----------------------------------------------------------*/ 25 | /* Private define ------------------------------------------------------------*/ 26 | /* Private macro -------------------------------------------------------------*/ 27 | /* Private variables ---------------------------------------------------------*/ 28 | TIM_HandleTypeDef htim2; 29 | /* Private function prototypes -----------------------------------------------*/ 30 | /* Private functions ---------------------------------------------------------*/ 31 | 32 | /** 33 | * @brief This function configures the TIM2 as a time base source. 34 | * The time source is configured to have 1ms time base with a dedicated 35 | * Tick interrupt priority. 36 | * @note This function is called automatically at the beginning of program after 37 | * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig(). 38 | * @param TickPriority: Tick interrupt priority. 39 | * @retval HAL status 40 | */ 41 | HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) 42 | { 43 | RCC_ClkInitTypeDef clkconfig; 44 | uint32_t uwTimclock = 0; 45 | uint32_t uwPrescalerValue = 0; 46 | uint32_t pFLatency; 47 | HAL_StatusTypeDef status; 48 | 49 | /* Enable TIM2 clock */ 50 | __HAL_RCC_TIM2_CLK_ENABLE(); 51 | 52 | /* Get clock configuration */ 53 | HAL_RCC_GetClockConfig(&clkconfig, &pFLatency); 54 | 55 | /* Compute TIM2 clock */ 56 | uwTimclock = HAL_RCC_GetPCLK1Freq(); 57 | 58 | /* Compute the prescaler value to have TIM2 counter clock equal to 1MHz */ 59 | uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U); 60 | 61 | /* Initialize TIM2 */ 62 | htim2.Instance = TIM2; 63 | 64 | /* Initialize TIMx peripheral as follow: 65 | 66 | + Period = [(TIM2CLK/1000) - 1]. to have a (1/1000) s time base. 67 | + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock. 68 | + ClockDivision = 0 69 | + Counter direction = Up 70 | */ 71 | htim2.Init.Period = (1000000U / 1000U) - 1U; 72 | htim2.Init.Prescaler = uwPrescalerValue; 73 | htim2.Init.ClockDivision = 0; 74 | htim2.Init.CounterMode = TIM_COUNTERMODE_UP; 75 | 76 | status = HAL_TIM_Base_Init(&htim2); 77 | if (status == HAL_OK) 78 | { 79 | /* Start the TIM time Base generation in interrupt mode */ 80 | status = HAL_TIM_Base_Start_IT(&htim2); 81 | if (status == HAL_OK) 82 | { 83 | /* Enable the TIM2 global Interrupt */ 84 | HAL_NVIC_EnableIRQ(TIM2_IRQn); 85 | /* Configure the SysTick IRQ priority */ 86 | if (TickPriority < (1UL << __NVIC_PRIO_BITS)) 87 | { 88 | /* Configure the TIM IRQ priority */ 89 | HAL_NVIC_SetPriority(TIM2_IRQn, TickPriority, 0U); 90 | uwTickPrio = TickPriority; 91 | } 92 | else 93 | { 94 | status = HAL_ERROR; 95 | } 96 | } 97 | } 98 | 99 | /* Return function status */ 100 | return status; 101 | } 102 | 103 | /** 104 | * @brief Suspend Tick increment. 105 | * @note Disable the tick increment by disabling TIM2 update interrupt. 106 | * @param None 107 | * @retval None 108 | */ 109 | void HAL_SuspendTick(void) 110 | { 111 | /* Disable TIM2 update Interrupt */ 112 | __HAL_TIM_DISABLE_IT(&htim2, TIM_IT_UPDATE); 113 | } 114 | 115 | /** 116 | * @brief Resume Tick increment. 117 | * @note Enable the tick increment by Enabling TIM2 update interrupt. 118 | * @param None 119 | * @retval None 120 | */ 121 | void HAL_ResumeTick(void) 122 | { 123 | /* Enable TIM2 Update interrupt */ 124 | __HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE); 125 | } 126 | 127 | -------------------------------------------------------------------------------- /firmware/Core/Src/stm32g4xx_it.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file stm32g4xx_it.c 5 | * @brief Interrupt Service Routines. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | * Copyright (c) 2023 STMicroelectronics. 10 | * All rights reserved. 11 | * 12 | * This software is licensed under terms that can be found in the LICENSE file 13 | * in the root directory of this software component. 14 | * If no LICENSE file comes with this software, it is provided AS-IS. 15 | * 16 | ****************************************************************************** 17 | */ 18 | /* USER CODE END Header */ 19 | 20 | /* Includes ------------------------------------------------------------------*/ 21 | #include "main.h" 22 | #include "stm32g4xx_it.h" 23 | /* Private includes ----------------------------------------------------------*/ 24 | /* USER CODE BEGIN Includes */ 25 | /* USER CODE END Includes */ 26 | 27 | /* Private typedef -----------------------------------------------------------*/ 28 | /* USER CODE BEGIN TD */ 29 | 30 | /* USER CODE END TD */ 31 | 32 | /* Private define ------------------------------------------------------------*/ 33 | /* USER CODE BEGIN PD */ 34 | 35 | /* USER CODE END PD */ 36 | 37 | /* Private macro -------------------------------------------------------------*/ 38 | /* USER CODE BEGIN PM */ 39 | 40 | /* USER CODE END PM */ 41 | 42 | /* Private variables ---------------------------------------------------------*/ 43 | /* USER CODE BEGIN PV */ 44 | 45 | /* USER CODE END PV */ 46 | 47 | /* Private function prototypes -----------------------------------------------*/ 48 | /* USER CODE BEGIN PFP */ 49 | 50 | /* USER CODE END PFP */ 51 | 52 | /* Private user code ---------------------------------------------------------*/ 53 | /* USER CODE BEGIN 0 */ 54 | 55 | /* USER CODE END 0 */ 56 | 57 | /* External variables --------------------------------------------------------*/ 58 | extern PCD_HandleTypeDef hpcd_USB_FS; 59 | extern DMA_HandleTypeDef hdma_adc1; 60 | extern DMA_HandleTypeDef hdma_adc2; 61 | extern ADC_HandleTypeDef hadc1; 62 | extern ADC_HandleTypeDef hadc2; 63 | extern FDCAN_HandleTypeDef hfdcan1; 64 | extern TIM_HandleTypeDef htim1; 65 | extern TIM_HandleTypeDef htim6; 66 | extern TIM_HandleTypeDef htim2; 67 | 68 | /* USER CODE BEGIN EV */ 69 | 70 | /* USER CODE END EV */ 71 | 72 | /******************************************************************************/ 73 | /* Cortex-M4 Processor Interruption and Exception Handlers */ 74 | /******************************************************************************/ 75 | /** 76 | * @brief This function handles Non maskable interrupt. 77 | */ 78 | void NMI_Handler(void) 79 | { 80 | /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ 81 | 82 | /* USER CODE END NonMaskableInt_IRQn 0 */ 83 | /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ 84 | while (1) 85 | { 86 | } 87 | /* USER CODE END NonMaskableInt_IRQn 1 */ 88 | } 89 | 90 | /** 91 | * @brief This function handles Hard fault interrupt. 92 | */ 93 | void HardFault_Handler(void) 94 | { 95 | /* USER CODE BEGIN HardFault_IRQn 0 */ 96 | 97 | /* USER CODE END HardFault_IRQn 0 */ 98 | while (1) 99 | { 100 | /* USER CODE BEGIN W1_HardFault_IRQn 0 */ 101 | /* USER CODE END W1_HardFault_IRQn 0 */ 102 | } 103 | } 104 | 105 | /** 106 | * @brief This function handles Memory management fault. 107 | */ 108 | void MemManage_Handler(void) 109 | { 110 | /* USER CODE BEGIN MemoryManagement_IRQn 0 */ 111 | 112 | /* USER CODE END MemoryManagement_IRQn 0 */ 113 | while (1) 114 | { 115 | /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ 116 | /* USER CODE END W1_MemoryManagement_IRQn 0 */ 117 | } 118 | } 119 | 120 | /** 121 | * @brief This function handles Prefetch fault, memory access fault. 122 | */ 123 | void BusFault_Handler(void) 124 | { 125 | /* USER CODE BEGIN BusFault_IRQn 0 */ 126 | 127 | /* USER CODE END BusFault_IRQn 0 */ 128 | while (1) 129 | { 130 | /* USER CODE BEGIN W1_BusFault_IRQn 0 */ 131 | /* USER CODE END W1_BusFault_IRQn 0 */ 132 | } 133 | } 134 | 135 | /** 136 | * @brief This function handles Undefined instruction or illegal state. 137 | */ 138 | void UsageFault_Handler(void) 139 | { 140 | /* USER CODE BEGIN UsageFault_IRQn 0 */ 141 | 142 | /* USER CODE END UsageFault_IRQn 0 */ 143 | while (1) 144 | { 145 | /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ 146 | /* USER CODE END W1_UsageFault_IRQn 0 */ 147 | } 148 | } 149 | 150 | /** 151 | * @brief This function handles Debug monitor. 152 | */ 153 | void DebugMon_Handler(void) 154 | { 155 | /* USER CODE BEGIN DebugMonitor_IRQn 0 */ 156 | 157 | /* USER CODE END DebugMonitor_IRQn 0 */ 158 | /* USER CODE BEGIN DebugMonitor_IRQn 1 */ 159 | 160 | /* USER CODE END DebugMonitor_IRQn 1 */ 161 | } 162 | 163 | /******************************************************************************/ 164 | /* STM32G4xx Peripheral Interrupt Handlers */ 165 | /* Add here the Interrupt Handlers for the used peripherals. */ 166 | /* For the available peripheral interrupt handler names, */ 167 | /* please refer to the startup file (startup_stm32g4xx.s). */ 168 | /******************************************************************************/ 169 | 170 | /** 171 | * @brief This function handles EXTI line1 interrupt. 172 | */ 173 | void EXTI1_IRQHandler(void) 174 | { 175 | /* USER CODE BEGIN EXTI1_IRQn 0 */ 176 | 177 | /* USER CODE END EXTI1_IRQn 0 */ 178 | HAL_GPIO_EXTI_IRQHandler(IFA_Pin); 179 | /* USER CODE BEGIN EXTI1_IRQn 1 */ 180 | 181 | /* USER CODE END EXTI1_IRQn 1 */ 182 | } 183 | 184 | /** 185 | * @brief This function handles DMA1 channel1 global interrupt. 186 | */ 187 | void DMA1_Channel1_IRQHandler(void) 188 | { 189 | /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */ 190 | 191 | /* USER CODE END DMA1_Channel1_IRQn 0 */ 192 | HAL_DMA_IRQHandler(&hdma_adc1); 193 | /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */ 194 | 195 | /* USER CODE END DMA1_Channel1_IRQn 1 */ 196 | } 197 | 198 | /** 199 | * @brief This function handles DMA1 channel2 global interrupt. 200 | */ 201 | void DMA1_Channel2_IRQHandler(void) 202 | { 203 | /* USER CODE BEGIN DMA1_Channel2_IRQn 0 */ 204 | 205 | /* USER CODE END DMA1_Channel2_IRQn 0 */ 206 | HAL_DMA_IRQHandler(&hdma_adc2); 207 | /* USER CODE BEGIN DMA1_Channel2_IRQn 1 */ 208 | 209 | /* USER CODE END DMA1_Channel2_IRQn 1 */ 210 | } 211 | 212 | /** 213 | * @brief This function handles ADC1 and ADC2 global interrupt. 214 | */ 215 | void ADC1_2_IRQHandler(void) 216 | { 217 | /* USER CODE BEGIN ADC1_2_IRQn 0 */ 218 | 219 | /* USER CODE END ADC1_2_IRQn 0 */ 220 | HAL_ADC_IRQHandler(&hadc1); 221 | HAL_ADC_IRQHandler(&hadc2); 222 | /* USER CODE BEGIN ADC1_2_IRQn 1 */ 223 | 224 | /* USER CODE END ADC1_2_IRQn 1 */ 225 | } 226 | 227 | /** 228 | * @brief This function handles USB low priority interrupt remap. 229 | */ 230 | void USB_LP_IRQHandler(void) 231 | { 232 | /* USER CODE BEGIN USB_LP_IRQn 0 */ 233 | 234 | /* USER CODE END USB_LP_IRQn 0 */ 235 | HAL_PCD_IRQHandler(&hpcd_USB_FS); 236 | /* USER CODE BEGIN USB_LP_IRQn 1 */ 237 | 238 | /* USER CODE END USB_LP_IRQn 1 */ 239 | } 240 | 241 | /** 242 | * @brief This function handles FDCAN1 interrupt 0. 243 | */ 244 | void FDCAN1_IT0_IRQHandler(void) 245 | { 246 | /* USER CODE BEGIN FDCAN1_IT0_IRQn 0 */ 247 | 248 | /* USER CODE END FDCAN1_IT0_IRQn 0 */ 249 | HAL_FDCAN_IRQHandler(&hfdcan1); 250 | /* USER CODE BEGIN FDCAN1_IT0_IRQn 1 */ 251 | 252 | /* USER CODE END FDCAN1_IT0_IRQn 1 */ 253 | } 254 | 255 | /** 256 | * @brief This function handles TIM1 trigger and commutation interrupts and TIM17 global interrupt. 257 | */ 258 | void TIM1_TRG_COM_TIM17_IRQHandler(void) 259 | { 260 | /* USER CODE BEGIN TIM1_TRG_COM_TIM17_IRQn 0 */ 261 | 262 | /* USER CODE END TIM1_TRG_COM_TIM17_IRQn 0 */ 263 | HAL_TIM_IRQHandler(&htim1); 264 | /* USER CODE BEGIN TIM1_TRG_COM_TIM17_IRQn 1 */ 265 | 266 | /* USER CODE END TIM1_TRG_COM_TIM17_IRQn 1 */ 267 | } 268 | 269 | /** 270 | * @brief This function handles TIM2 global interrupt. 271 | */ 272 | void TIM2_IRQHandler(void) 273 | { 274 | /* USER CODE BEGIN TIM2_IRQn 0 */ 275 | 276 | /* USER CODE END TIM2_IRQn 0 */ 277 | HAL_TIM_IRQHandler(&htim2); 278 | /* USER CODE BEGIN TIM2_IRQn 1 */ 279 | 280 | /* USER CODE END TIM2_IRQn 1 */ 281 | } 282 | 283 | /** 284 | * @brief This function handles TIM6 global interrupt, DAC1 and DAC3 channel underrun error interrupts. 285 | */ 286 | void TIM6_DAC_IRQHandler(void) 287 | { 288 | /* USER CODE BEGIN TIM6_DAC_IRQn 0 */ 289 | 290 | /* USER CODE END TIM6_DAC_IRQn 0 */ 291 | HAL_TIM_IRQHandler(&htim6); 292 | /* USER CODE BEGIN TIM6_DAC_IRQn 1 */ 293 | 294 | /* USER CODE END TIM6_DAC_IRQn 1 */ 295 | } 296 | 297 | /* USER CODE BEGIN 1 */ 298 | 299 | /* USER CODE END 1 */ 300 | -------------------------------------------------------------------------------- /firmware/Core/Src/trig_luts.c: -------------------------------------------------------------------------------- 1 | #include "trig_luts.h" 2 | 3 | 4 | // Full sin wave from () 5 | // Saves some logic and a few addition operations 6 | // with a trade-off in memory 7 | // TODO: Possibly build LUT at runtime on startup? 8 | uint8_t sin_lut_data[] = { 9 | 128, 131, 134, 137, 140, 143, 146, 149, 153, 156, 159, 162, 165, 10 | 168, 171, 174, 177, 180, 182, 185, 188, 191, 194, 196, 199, 201, 11 | 204, 207, 209, 211, 214, 216, 218, 220, 223, 225, 227, 229, 231, 12 | 232, 234, 236, 238, 239, 241, 242, 243, 245, 246, 247, 248, 249, 13 | 250, 251, 252, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255, 14 | 255, 255, 255, 255, 254, 254, 253, 253, 252, 251, 251, 250, 249, 15 | 248, 247, 245, 244, 243, 241, 240, 238, 237, 235, 233, 232, 230, 16 | 228, 226, 224, 222, 219, 217, 215, 213, 210, 208, 205, 203, 200, 17 | 198, 195, 192, 189, 187, 184, 181, 178, 175, 172, 169, 166, 163, 18 | 160, 157, 154, 151, 148, 145, 142, 139, 135, 132, 129, 126, 123, 19 | 120, 116, 113, 110, 107, 104, 101, 98, 95, 92, 89, 86, 83, 20 | 80, 77, 74, 71, 68, 66, 63, 60, 57, 55, 52, 50, 47, 21 | 45, 42, 40, 38, 36, 33, 31, 29, 27, 25, 23, 22, 20, 22 | 18, 17, 15, 14, 12, 11, 10, 8, 7, 6, 5, 4, 4, 23 | 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 24 | 0, 0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 25 | 10, 12, 13, 14, 16, 17, 19, 21, 23, 24, 26, 28, 30, 26 | 32, 35, 37, 39, 41, 44, 46, 48, 51, 54, 56, 59, 61, 27 | 64, 67, 70, 73, 75, 78, 81, 84, 87, 90, 93, 96, 99, 28 | 102, 106, 109, 112, 115, 118, 121, 124, 127 29 | }; 30 | 31 | // Returns sin(x) * 0.5 + 0.5 in uint8 32 | // 0 = 0.0 and 256 = 2*pi 33 | uint8_t get_sin_lut_value(uint8_t position){ 34 | return sin_lut_data[position]; 35 | } 36 | 37 | // Index wraparound version of previous 38 | uint8_t get_sin_lut_value_index_safe(uint8_t position){ 39 | position %= 256; 40 | return get_sin_lut_value(position); 41 | } 42 | 43 | // Returns sin(x) * value/2 + value/2 44 | uint8_t mult_sin_lut_uint8(uint8_t position, uint8_t value){ 45 | // (uint8 * uint8) / 256 46 | uint16_t mult_value = (uint16_t)value * get_sin_lut_value_index_safe(position); 47 | return (uint8_t)(mult_value >> 8); 48 | } 49 | 50 | int16_t mult_sin_lut_int16(uint8_t position, int16_t value){ 51 | // (uint16 * uint8) / 256 52 | int32_t mult_value = (value * (get_sin_lut_value_index_safe(position) - 128)) * 2; 53 | return (int16_t)(mult_value >> 8); 54 | } -------------------------------------------------------------------------------- /firmware/Core/Src/utils.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | int16_t int16_min3(int16_t a, int16_t b, int16_t c) { 4 | int16_t min = a; 5 | if (b < min) { 6 | min = b; 7 | } 8 | if (c < min) { 9 | min = c; 10 | } 11 | return min; 12 | } 13 | 14 | int bound(int value, int min, int max){ 15 | if(value < min){ 16 | return min; 17 | }else if(value > max){ 18 | return max; 19 | }else{ 20 | return value; 21 | } 22 | } 23 | 24 | bool enforce_bound(int *value, int min, int max){ 25 | if(*value < min){ 26 | *value = min; 27 | return true; 28 | }else if(*value > max){ 29 | *value = max; 30 | return true; 31 | }else{ 32 | return false; 33 | } 34 | } -------------------------------------------------------------------------------- /firmware/Makefile: -------------------------------------------------------------------------------- 1 | ########################################################################################################################## 2 | # File automatically-generated by tool: [projectgenerator] version: [4.1.0] date: [Sun Jan 28 13:48:57 CST 2024] 3 | ########################################################################################################################## 4 | 5 | # ------------------------------------------------ 6 | # Generic Makefile (based on gcc) 7 | # 8 | # ChangeLog : 9 | # 2017-02-10 - Several enhancements + project update mode 10 | # 2015-07-22 - first version 11 | # ------------------------------------------------ 12 | 13 | ###################################### 14 | # target 15 | ###################################### 16 | TARGET = 50x50_DRIVE 17 | 18 | 19 | ###################################### 20 | # building variables 21 | ###################################### 22 | # debug build? 23 | DEBUG = 1 24 | # optimization 25 | OPT = -Og 26 | 27 | 28 | ####################################### 29 | # paths 30 | ####################################### 31 | # Build path 32 | BUILD_DIR = build 33 | 34 | ###################################### 35 | # source 36 | ###################################### 37 | # C sources 38 | C_SOURCES = \ 39 | Core/Src/main.c \ 40 | Core/Src/app_freertos.c \ 41 | Core/Src/stm32g4xx_it.c \ 42 | Core/Src/stm32g4xx_hal_msp.c \ 43 | Core/Src/stm32g4xx_hal_timebase_tim.c \ 44 | USB_Device/App/usb_device.c \ 45 | USB_Device/App/usbd_desc.c \ 46 | USB_Device/App/usbd_cdc_if.c \ 47 | USB_Device/Target/usbd_conf.c \ 48 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pcd.c \ 49 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pcd_ex.c \ 50 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_ll_usb.c \ 51 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal.c \ 52 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_rcc.c \ 53 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_rcc_ex.c \ 54 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash.c \ 55 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash_ex.c \ 56 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash_ramfunc.c \ 57 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_gpio.c \ 58 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_exti.c \ 59 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_dma.c \ 60 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_dma_ex.c \ 61 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr.c \ 62 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr_ex.c \ 63 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_cortex.c \ 64 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_adc.c \ 65 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_adc_ex.c \ 66 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_ll_adc.c \ 67 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_i2c.c \ 68 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_i2c_ex.c \ 69 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_lptim.c \ 70 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_tim.c \ 71 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_tim_ex.c \ 72 | Core/Src/system_stm32g4xx.c \ 73 | Middlewares/Third_Party/FreeRTOS/Source/croutine.c \ 74 | Middlewares/Third_Party/FreeRTOS/Source/event_groups.c \ 75 | Middlewares/Third_Party/FreeRTOS/Source/list.c \ 76 | Middlewares/Third_Party/FreeRTOS/Source/queue.c \ 77 | Middlewares/Third_Party/FreeRTOS/Source/stream_buffer.c \ 78 | Middlewares/Third_Party/FreeRTOS/Source/tasks.c \ 79 | Middlewares/Third_Party/FreeRTOS/Source/timers.c \ 80 | Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.c \ 81 | Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c \ 82 | Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c \ 83 | Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c \ 84 | Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c \ 85 | Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c \ 86 | Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c \ 87 | Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_fdcan.c 88 | 89 | # ASM sources 90 | ASM_SOURCES = \ 91 | startup_stm32g431xx.s 92 | 93 | 94 | ####################################### 95 | # binaries 96 | ####################################### 97 | PREFIX = arm-none-eabi- 98 | # The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx) 99 | # either it can be added to the PATH environment variable. 100 | ifdef GCC_PATH 101 | CC = $(GCC_PATH)/$(PREFIX)gcc 102 | AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp 103 | CP = $(GCC_PATH)/$(PREFIX)objcopy 104 | SZ = $(GCC_PATH)/$(PREFIX)size 105 | else 106 | CC = $(PREFIX)gcc 107 | AS = $(PREFIX)gcc -x assembler-with-cpp 108 | CP = $(PREFIX)objcopy 109 | SZ = $(PREFIX)size 110 | endif 111 | HEX = $(CP) -O ihex 112 | BIN = $(CP) -O binary -S 113 | 114 | ####################################### 115 | # CFLAGS 116 | ####################################### 117 | # cpu 118 | CPU = -mcpu=cortex-m4 119 | 120 | # fpu 121 | FPU = -mfpu=fpv4-sp-d16 122 | 123 | # float-abi 124 | FLOAT-ABI = -mfloat-abi=hard 125 | 126 | # mcu 127 | MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI) 128 | 129 | # macros for gcc 130 | # AS defines 131 | AS_DEFS = 132 | 133 | # C defines 134 | C_DEFS = \ 135 | -DUSE_HAL_DRIVER \ 136 | -DSTM32G431xx 137 | 138 | 139 | # AS includes 140 | AS_INCLUDES = \ 141 | -ICore/Inc 142 | 143 | # C includes 144 | C_INCLUDES = \ 145 | -ICore/Inc \ 146 | -IUSB_Device/App \ 147 | -IUSB_Device/Target \ 148 | -IDrivers/STM32G4xx_HAL_Driver/Inc \ 149 | -IDrivers/STM32G4xx_HAL_Driver/Inc/Legacy \ 150 | -IMiddlewares/Third_Party/FreeRTOS/Source/include \ 151 | -IMiddlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 \ 152 | -IMiddlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F \ 153 | -IMiddlewares/ST/STM32_USB_Device_Library/Core/Inc \ 154 | -IMiddlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc \ 155 | -IDrivers/CMSIS/Device/ST/STM32G4xx/Include \ 156 | -IDrivers/CMSIS/Include 157 | 158 | 159 | # compile gcc flags 160 | ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections 161 | 162 | CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections 163 | 164 | ifeq ($(DEBUG), 1) 165 | CFLAGS += -g -gdwarf-2 166 | endif 167 | 168 | 169 | # Generate dependency information 170 | CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" 171 | 172 | 173 | ####################################### 174 | # LDFLAGS 175 | ####################################### 176 | # link script 177 | LDSCRIPT = STM32G431CBUx_FLASH.ld 178 | 179 | # libraries 180 | LIBS = -lc -lm -lnosys 181 | LIBDIR = 182 | LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections 183 | 184 | # default action: build all 185 | all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin 186 | 187 | 188 | ####################################### 189 | # build the application 190 | ####################################### 191 | # list of objects 192 | OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o))) 193 | vpath %.c $(sort $(dir $(C_SOURCES))) 194 | # list of ASM program objects 195 | OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o))) 196 | vpath %.s $(sort $(dir $(ASM_SOURCES))) 197 | 198 | $(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) 199 | $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@ 200 | 201 | $(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR) 202 | $(AS) -c $(CFLAGS) $< -o $@ 203 | 204 | $(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile 205 | $(CC) $(OBJECTS) $(LDFLAGS) -o $@ 206 | $(SZ) $@ 207 | 208 | $(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR) 209 | $(HEX) $< $@ 210 | 211 | $(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR) 212 | $(BIN) $< $@ 213 | 214 | $(BUILD_DIR): 215 | mkdir $@ 216 | 217 | ####################################### 218 | # clean up 219 | ####################################### 220 | clean: 221 | -rm -fR $(BUILD_DIR) 222 | 223 | ####################################### 224 | # dependencies 225 | ####################################### 226 | -include $(wildcard $(BUILD_DIR)/*.d) 227 | 228 | # *** EOF *** 229 | -------------------------------------------------------------------------------- /firmware/STM32-for-VSCode.config.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for the STM32 for VSCode extension 2 | # Arrays can be inputted in two ways. One is: [entry_1, entry_2, ..., entry_final] 3 | # or by adding an indented list below the variable name e.g.: 4 | # VARIABLE: 5 | # - entry_1 6 | # - entry_2 7 | 8 | # The project name 9 | target: 50x50_DRIVE 10 | # Can be C or C++ 11 | language: C 12 | 13 | optimization: Og 14 | 15 | # MCU settings 16 | targetMCU: stm32g4x 17 | cpu: cortex-m4 # type of cpu e.g. cortex-m4 18 | fpu: fpv4-sp-d16 # Defines how floating points are defined. Can be left empty. 19 | floatAbi: -mfloat-abi=hard 20 | ldscript: STM32G431CBUx_FLASH.ld # linker script 21 | 22 | # Compiler definitions. The -D prefix for the compiler will be automatically added. 23 | cDefinitions: [] 24 | cxxDefinitions: [] 25 | asDefinitions: [] 26 | 27 | # Compiler definition files. you can add a single files or an array of files for different definitions. 28 | # The file is expected to have a definition each new line. 29 | # This allows to include for example a .definition file which can be ignored in git and can contain 30 | # This can be convenient for passing along secrets at compile time, or generating a file for per device setup. 31 | cDefinitionsFile: 32 | cxxDefinitionsFile: 33 | asDefinitionsFile: 34 | 35 | # Compiler flags 36 | cFlags: 37 | - -Wall 38 | - -fdata-sections 39 | - -ffunction-sections 40 | 41 | cxxFlags: [] 42 | assemblyFlags: 43 | - -Wall 44 | - -fdata-sections 45 | - -ffunction-sections 46 | 47 | linkerFlags: [] 48 | 49 | # libraries to be included. The -l prefix to the library will be automatically added. 50 | libraries: 51 | - c 52 | - m 53 | 54 | # Library directories. Folders can be added here that contain custom libraries. 55 | libraryDirectories: [] 56 | 57 | # Files or folders that will be excluded from compilation. 58 | # Glob patterns (https://www.wikiwand.com/en/Glob_(programming)) can be used. 59 | # Do mind that double stars are reserved in yaml 60 | # these should be escaped with a: \ or the name should be in double quotes e.g. "**.test.**" 61 | excludes: 62 | - "**/Examples/**" 63 | - "**/examples/**" 64 | - "**/Example/**" 65 | - "**/example/**" 66 | - "**_template.*" 67 | 68 | 69 | # Include directories (directories containing .h or .hpp files) 70 | # If a CubeMX makefile is present it will automatically include the include directories from that makefile. 71 | includeDirectories: 72 | - Inc/** 73 | - Core/Inc/** 74 | - Core/Lib/** 75 | - Src/** 76 | - Core/Src/** 77 | - Core/Lib/** 78 | 79 | 80 | # Files that should be included in the compilation. 81 | # If a CubeMX makefile is present it will automatically include the c and cpp/cxx files from that makefile. 82 | # Glob patterns (https://www.wikiwand.com/en/Glob_(programming)) can be used. 83 | # Do mind that double stars are reserved in yaml 84 | # these should be escaped with a: \ or the name should be in double quotes e.g. "HARDWARE_DRIVER*.c" 85 | sourceFiles: 86 | - Src/** 87 | - Core/Src/** 88 | - Core/Lib/** 89 | 90 | 91 | # When no makefile is present it will show a warning pop-up. 92 | # However when compilation without the CubeMX Makefile is desired, this can be turned of. 93 | suppressMakefileWarning: false 94 | 95 | # Custom makefile rules 96 | # Here custom makefile rules can be added to the STM32Make.make file 97 | # an example of how this can be used is commented out below. 98 | customMakefileRules: 99 | # - command: sayhello 100 | # rule: echo "hello" 101 | # dependsOn: $(BUILD_DIR)/$(TARGET).elf # can be left out 102 | 103 | # Additional flags which will be used when invoking the make command 104 | makeFlags: 105 | # - -O # use this option when the output of make is mixed up only works for make version 4.0 and upwards 106 | # - --silent # use this option to silence the output of the build 107 | -------------------------------------------------------------------------------- /firmware/STM32G431CBUx_FLASH.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************************** 3 | ** 4 | 5 | ** File : LinkerScript.ld 6 | ** 7 | ** Author : STM32CubeMX 8 | ** 9 | ** Abstract : Linker script for STM32G431CBUx series 10 | ** 128Kbytes FLASH and 32Kbytes RAM 11 | ** 12 | ** Set heap size, stack size and stack location according 13 | ** to application requirements. 14 | ** 15 | ** Set memory bank area and size if external memory is used. 16 | ** 17 | ** Target : STMicroelectronics STM32 18 | ** 19 | ** Distribution: The file is distributed “as is,” without any warranty 20 | ** of any kind. 21 | ** 22 | ***************************************************************************** 23 | ** @attention 24 | ** 25 | **

© COPYRIGHT(c) 2019 STMicroelectronics

26 | ** 27 | ** Redistribution and use in source and binary forms, with or without modification, 28 | ** are permitted provided that the following conditions are met: 29 | ** 1. Redistributions of source code must retain the above copyright notice, 30 | ** this list of conditions and the following disclaimer. 31 | ** 2. Redistributions in binary form must reproduce the above copyright notice, 32 | ** this list of conditions and the following disclaimer in the documentation 33 | ** and/or other materials provided with the distribution. 34 | ** 3. Neither the name of STMicroelectronics nor the names of its contributors 35 | ** may be used to endorse or promote products derived from this software 36 | ** without specific prior written permission. 37 | ** 38 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 39 | ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 41 | ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 42 | ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 43 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 44 | ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 45 | ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 46 | ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 47 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 48 | ** 49 | ***************************************************************************** 50 | */ 51 | 52 | /* Entry Point */ 53 | ENTRY(Reset_Handler) 54 | 55 | /* Highest address of the user mode stack */ 56 | _estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM */ 57 | /* Generate a link error if heap and stack don't fit into RAM */ 58 | _Min_Heap_Size = 0x200; /* required amount of heap */ 59 | _Min_Stack_Size = 0x400; /* required amount of stack */ 60 | 61 | /* Specify the memory areas */ 62 | MEMORY 63 | { 64 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K 65 | FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K 66 | } 67 | 68 | /* Define output sections */ 69 | SECTIONS 70 | { 71 | /* The startup code goes first into FLASH */ 72 | .isr_vector : 73 | { 74 | . = ALIGN(4); 75 | KEEP(*(.isr_vector)) /* Startup code */ 76 | . = ALIGN(4); 77 | } >FLASH 78 | 79 | /* The program code and other data goes into FLASH */ 80 | .text : 81 | { 82 | . = ALIGN(4); 83 | *(.text) /* .text sections (code) */ 84 | *(.text*) /* .text* sections (code) */ 85 | *(.glue_7) /* glue arm to thumb code */ 86 | *(.glue_7t) /* glue thumb to arm code */ 87 | *(.eh_frame) 88 | 89 | KEEP (*(.init)) 90 | KEEP (*(.fini)) 91 | 92 | . = ALIGN(4); 93 | _etext = .; /* define a global symbols at end of code */ 94 | } >FLASH 95 | 96 | /* Constant data goes into FLASH */ 97 | .rodata : 98 | { 99 | . = ALIGN(4); 100 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 101 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 102 | . = ALIGN(4); 103 | } >FLASH 104 | 105 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH 106 | .ARM : { 107 | __exidx_start = .; 108 | *(.ARM.exidx*) 109 | __exidx_end = .; 110 | } >FLASH 111 | 112 | .preinit_array : 113 | { 114 | PROVIDE_HIDDEN (__preinit_array_start = .); 115 | KEEP (*(.preinit_array*)) 116 | PROVIDE_HIDDEN (__preinit_array_end = .); 117 | } >FLASH 118 | .init_array : 119 | { 120 | PROVIDE_HIDDEN (__init_array_start = .); 121 | KEEP (*(SORT(.init_array.*))) 122 | KEEP (*(.init_array*)) 123 | PROVIDE_HIDDEN (__init_array_end = .); 124 | } >FLASH 125 | .fini_array : 126 | { 127 | PROVIDE_HIDDEN (__fini_array_start = .); 128 | KEEP (*(SORT(.fini_array.*))) 129 | KEEP (*(.fini_array*)) 130 | PROVIDE_HIDDEN (__fini_array_end = .); 131 | } >FLASH 132 | 133 | /* used by the startup to initialize data */ 134 | _sidata = LOADADDR(.data); 135 | 136 | /* Initialized data sections goes into RAM, load LMA copy after code */ 137 | .data : 138 | { 139 | . = ALIGN(4); 140 | _sdata = .; /* create a global symbol at data start */ 141 | *(.data) /* .data sections */ 142 | *(.data*) /* .data* sections */ 143 | 144 | . = ALIGN(4); 145 | _edata = .; /* define a global symbol at data end */ 146 | } >RAM AT> FLASH 147 | 148 | 149 | /* Uninitialized data section */ 150 | . = ALIGN(4); 151 | .bss : 152 | { 153 | /* This is used by the startup in order to initialize the .bss secion */ 154 | _sbss = .; /* define a global symbol at bss start */ 155 | __bss_start__ = _sbss; 156 | *(.bss) 157 | *(.bss*) 158 | *(COMMON) 159 | 160 | . = ALIGN(4); 161 | _ebss = .; /* define a global symbol at bss end */ 162 | __bss_end__ = _ebss; 163 | } >RAM 164 | 165 | /* User_heap_stack section, used to check that there is enough RAM left */ 166 | ._user_heap_stack : 167 | { 168 | . = ALIGN(8); 169 | PROVIDE ( end = . ); 170 | PROVIDE ( _end = . ); 171 | . = . + _Min_Heap_Size; 172 | . = . + _Min_Stack_Size; 173 | . = ALIGN(8); 174 | } >RAM 175 | 176 | 177 | 178 | /* Remove information from the standard libraries */ 179 | /DISCARD/ : 180 | { 181 | libc.a ( * ) 182 | libm.a ( * ) 183 | libgcc.a ( * ) 184 | } 185 | 186 | .ARM.attributes 0 : { *(.ARM.attributes) } 187 | } 188 | 189 | 190 | -------------------------------------------------------------------------------- /firmware/USB_Device/App/usb_device.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : usb_device.c 5 | * @version : v3.0_Cube 6 | * @brief : This file implements the USB Device 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Includes ------------------------------------------------------------------*/ 22 | 23 | #include "usb_device.h" 24 | #include "usbd_core.h" 25 | #include "usbd_desc.h" 26 | #include "usbd_cdc.h" 27 | #include "usbd_cdc_if.h" 28 | 29 | /* USER CODE BEGIN Includes */ 30 | 31 | /* USER CODE END Includes */ 32 | 33 | /* USER CODE BEGIN PV */ 34 | /* Private variables ---------------------------------------------------------*/ 35 | 36 | /* USER CODE END PV */ 37 | 38 | /* USER CODE BEGIN PFP */ 39 | /* Private function prototypes -----------------------------------------------*/ 40 | 41 | /* USER CODE END PFP */ 42 | 43 | extern void Error_Handler(void); 44 | /* USB Device Core handle declaration. */ 45 | USBD_HandleTypeDef hUsbDeviceFS; 46 | extern USBD_DescriptorsTypeDef CDC_Desc; 47 | 48 | /* 49 | * -- Insert your variables declaration here -- 50 | */ 51 | /* USER CODE BEGIN 0 */ 52 | 53 | /* USER CODE END 0 */ 54 | 55 | /* 56 | * -- Insert your external function declaration here -- 57 | */ 58 | /* USER CODE BEGIN 1 */ 59 | 60 | /* USER CODE END 1 */ 61 | 62 | /** 63 | * Init USB device Library, add supported class and start the library 64 | * @retval None 65 | */ 66 | void MX_USB_Device_Init(void) 67 | { 68 | /* USER CODE BEGIN USB_Device_Init_PreTreatment */ 69 | 70 | /* USER CODE END USB_Device_Init_PreTreatment */ 71 | 72 | /* Init Device Library, add supported class and start the library. */ 73 | if (USBD_Init(&hUsbDeviceFS, &CDC_Desc, DEVICE_FS) != USBD_OK) { 74 | Error_Handler(); 75 | } 76 | if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK) { 77 | Error_Handler(); 78 | } 79 | if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK) { 80 | Error_Handler(); 81 | } 82 | if (USBD_Start(&hUsbDeviceFS) != USBD_OK) { 83 | Error_Handler(); 84 | } 85 | /* USER CODE BEGIN USB_Device_Init_PostTreatment */ 86 | 87 | /* USER CODE END USB_Device_Init_PostTreatment */ 88 | } 89 | 90 | /** 91 | * @} 92 | */ 93 | 94 | /** 95 | * @} 96 | */ 97 | 98 | -------------------------------------------------------------------------------- /firmware/USB_Device/App/usb_device.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : usb_device.h 5 | * @version : v3.0_Cube 6 | * @brief : Header for usb_device.c file. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __USB_DEVICE__H__ 23 | #define __USB_DEVICE__H__ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Includes ------------------------------------------------------------------*/ 30 | #include "stm32g4xx.h" 31 | #include "stm32g4xx_hal.h" 32 | #include "usbd_def.h" 33 | 34 | /* USER CODE BEGIN INCLUDE */ 35 | 36 | /* USER CODE END INCLUDE */ 37 | 38 | /** @addtogroup USBD_OTG_DRIVER 39 | * @{ 40 | */ 41 | 42 | /** @defgroup USBD_DEVICE USBD_DEVICE 43 | * @brief Device file for Usb otg low level driver. 44 | * @{ 45 | */ 46 | 47 | /** @defgroup USBD_DEVICE_Exported_Variables USBD_DEVICE_Exported_Variables 48 | * @brief Public variables. 49 | * @{ 50 | */ 51 | 52 | /* Private variables ---------------------------------------------------------*/ 53 | /* USER CODE BEGIN PV */ 54 | 55 | /* USER CODE END PV */ 56 | 57 | /* Private function prototypes -----------------------------------------------*/ 58 | /* USER CODE BEGIN PFP */ 59 | 60 | /* USER CODE END PFP */ 61 | 62 | /* 63 | * -- Insert your variables declaration here -- 64 | */ 65 | /* USER CODE BEGIN VARIABLES */ 66 | 67 | /* USER CODE END VARIABLES */ 68 | /** 69 | * @} 70 | */ 71 | 72 | /** @defgroup USBD_DEVICE_Exported_FunctionsPrototype USBD_DEVICE_Exported_FunctionsPrototype 73 | * @brief Declaration of public functions for Usb device. 74 | * @{ 75 | */ 76 | 77 | /** USB Device initialization function. */ 78 | void MX_USB_Device_Init(void); 79 | 80 | /* 81 | * -- Insert functions declaration here -- 82 | */ 83 | /* USER CODE BEGIN FD */ 84 | 85 | /* USER CODE END FD */ 86 | /** 87 | * @} 88 | */ 89 | 90 | /** 91 | * @} 92 | */ 93 | 94 | /** 95 | * @} 96 | */ 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif 101 | 102 | #endif /* __USB_DEVICE__H__ */ 103 | 104 | -------------------------------------------------------------------------------- /firmware/USB_Device/App/usbd_cdc_if.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : usbd_cdc_if.h 5 | * @version : v3.0_Cube 6 | * @brief : Header for usbd_cdc_if.c file. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __USBD_CDC_IF_H__ 23 | #define __USBD_CDC_IF_H__ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Includes ------------------------------------------------------------------*/ 30 | #include "usbd_cdc.h" 31 | 32 | /* USER CODE BEGIN INCLUDE */ 33 | 34 | /* USER CODE END INCLUDE */ 35 | 36 | /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY 37 | * @brief For Usb device. 38 | * @{ 39 | */ 40 | 41 | /** @defgroup USBD_CDC_IF USBD_CDC_IF 42 | * @brief Usb VCP device module 43 | * @{ 44 | */ 45 | 46 | /** @defgroup USBD_CDC_IF_Exported_Defines USBD_CDC_IF_Exported_Defines 47 | * @brief Defines. 48 | * @{ 49 | */ 50 | /* Define size for the receive and transmit buffer over CDC */ 51 | #define APP_RX_DATA_SIZE 1024 52 | #define APP_TX_DATA_SIZE 1024 53 | /* USER CODE BEGIN EXPORTED_DEFINES */ 54 | 55 | /* USER CODE END EXPORTED_DEFINES */ 56 | 57 | /** 58 | * @} 59 | */ 60 | 61 | /** @defgroup USBD_CDC_IF_Exported_Types USBD_CDC_IF_Exported_Types 62 | * @brief Types. 63 | * @{ 64 | */ 65 | 66 | /* USER CODE BEGIN EXPORTED_TYPES */ 67 | 68 | /* USER CODE END EXPORTED_TYPES */ 69 | 70 | /** 71 | * @} 72 | */ 73 | 74 | /** @defgroup USBD_CDC_IF_Exported_Macros USBD_CDC_IF_Exported_Macros 75 | * @brief Aliases. 76 | * @{ 77 | */ 78 | 79 | /* USER CODE BEGIN EXPORTED_MACRO */ 80 | 81 | /* USER CODE END EXPORTED_MACRO */ 82 | 83 | /** 84 | * @} 85 | */ 86 | 87 | /** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables 88 | * @brief Public variables. 89 | * @{ 90 | */ 91 | 92 | /** CDC Interface callback. */ 93 | extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; 94 | 95 | /* USER CODE BEGIN EXPORTED_VARIABLES */ 96 | 97 | /* USER CODE END EXPORTED_VARIABLES */ 98 | 99 | /** 100 | * @} 101 | */ 102 | 103 | /** @defgroup USBD_CDC_IF_Exported_FunctionsPrototype USBD_CDC_IF_Exported_FunctionsPrototype 104 | * @brief Public functions declaration. 105 | * @{ 106 | */ 107 | 108 | uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len); 109 | 110 | /* USER CODE BEGIN EXPORTED_FUNCTIONS */ 111 | 112 | /* USER CODE END EXPORTED_FUNCTIONS */ 113 | 114 | /** 115 | * @} 116 | */ 117 | 118 | /** 119 | * @} 120 | */ 121 | 122 | /** 123 | * @} 124 | */ 125 | 126 | #ifdef __cplusplus 127 | } 128 | #endif 129 | 130 | #endif /* __USBD_CDC_IF_H__ */ 131 | 132 | -------------------------------------------------------------------------------- /firmware/USB_Device/App/usbd_desc.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : usbd_desc.c 5 | * @version : v3.0_Cube 6 | * @brief : Header for usbd_conf.c file. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __USBD_DESC__C__ 23 | #define __USBD_DESC__C__ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Includes ------------------------------------------------------------------*/ 30 | #include "usbd_def.h" 31 | 32 | /* USER CODE BEGIN INCLUDE */ 33 | 34 | /* USER CODE END INCLUDE */ 35 | 36 | /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY 37 | * @{ 38 | */ 39 | 40 | /** @defgroup USBD_DESC USBD_DESC 41 | * @brief Usb device descriptors module. 42 | * @{ 43 | */ 44 | 45 | /** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants 46 | * @brief Constants. 47 | * @{ 48 | */ 49 | #define DEVICE_ID1 (UID_BASE) 50 | #define DEVICE_ID2 (UID_BASE + 0x4) 51 | #define DEVICE_ID3 (UID_BASE + 0x8) 52 | 53 | #define USB_SIZ_STRING_SERIAL 0x1A 54 | 55 | /* USER CODE BEGIN EXPORTED_CONSTANTS */ 56 | 57 | /* USER CODE END EXPORTED_CONSTANTS */ 58 | 59 | /** 60 | * @} 61 | */ 62 | 63 | /** @defgroup USBD_DESC_Exported_Defines USBD_DESC_Exported_Defines 64 | * @brief Defines. 65 | * @{ 66 | */ 67 | 68 | /* USER CODE BEGIN EXPORTED_DEFINES */ 69 | 70 | /* USER CODE END EXPORTED_DEFINES */ 71 | 72 | /** 73 | * @} 74 | */ 75 | 76 | /** @defgroup USBD_DESC_Exported_TypesDefinitions USBD_DESC_Exported_TypesDefinitions 77 | * @brief Types. 78 | * @{ 79 | */ 80 | 81 | /* USER CODE BEGIN EXPORTED_TYPES */ 82 | 83 | /* USER CODE END EXPORTED_TYPES */ 84 | 85 | /** 86 | * @} 87 | */ 88 | 89 | /** @defgroup USBD_DESC_Exported_Macros USBD_DESC_Exported_Macros 90 | * @brief Aliases. 91 | * @{ 92 | */ 93 | 94 | /* USER CODE BEGIN EXPORTED_MACRO */ 95 | 96 | /* USER CODE END EXPORTED_MACRO */ 97 | 98 | /** 99 | * @} 100 | */ 101 | 102 | /** @defgroup USBD_DESC_Exported_Variables USBD_DESC_Exported_Variables 103 | * @brief Public variables. 104 | * @{ 105 | */ 106 | 107 | extern USBD_DescriptorsTypeDef CDC_Desc; 108 | 109 | /* USER CODE BEGIN EXPORTED_VARIABLES */ 110 | 111 | /* USER CODE END EXPORTED_VARIABLES */ 112 | 113 | /** 114 | * @} 115 | */ 116 | 117 | /** @defgroup USBD_DESC_Exported_FunctionsPrototype USBD_DESC_Exported_FunctionsPrototype 118 | * @brief Public functions declaration. 119 | * @{ 120 | */ 121 | 122 | /* USER CODE BEGIN EXPORTED_FUNCTIONS */ 123 | 124 | /* USER CODE END EXPORTED_FUNCTIONS */ 125 | 126 | /** 127 | * @} 128 | */ 129 | 130 | /** 131 | * @} 132 | */ 133 | 134 | /** 135 | * @} 136 | */ 137 | 138 | #ifdef __cplusplus 139 | } 140 | #endif 141 | 142 | #endif /* __USBD_DESC__C__ */ 143 | 144 | -------------------------------------------------------------------------------- /firmware/USB_Device/Target/usbd_conf.h: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : usbd_conf.h 5 | * @version : v3.0_Cube 6 | * @brief : Header for usbd_conf.c file. 7 | ****************************************************************************** 8 | * @attention 9 | * 10 | * Copyright (c) 2023 STMicroelectronics. 11 | * All rights reserved. 12 | * 13 | * This software is licensed under terms that can be found in the LICENSE file 14 | * in the root directory of this software component. 15 | * If no LICENSE file comes with this software, it is provided AS-IS. 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __USBD_CONF__H__ 23 | #define __USBD_CONF__H__ 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* Includes ------------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include 33 | #include "stm32g4xx.h" 34 | #include "stm32g4xx_hal.h" 35 | 36 | /* USER CODE BEGIN INCLUDE */ 37 | 38 | /* USER CODE END INCLUDE */ 39 | 40 | /** @addtogroup USBD_OTG_DRIVER 41 | * @brief Driver for Usb device. 42 | * @{ 43 | */ 44 | 45 | /** @defgroup USBD_CONF USBD_CONF 46 | * @brief Configuration file for Usb otg low level driver. 47 | * @{ 48 | */ 49 | 50 | /** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables 51 | * @brief Public variables. 52 | * @{ 53 | */ 54 | 55 | /* Private variables ---------------------------------------------------------*/ 56 | /* USER CODE BEGIN PV */ 57 | /* USER CODE END PV */ 58 | /** 59 | * @} 60 | */ 61 | 62 | /** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines 63 | * @brief Defines for configuration of the Usb device. 64 | * @{ 65 | */ 66 | 67 | /*---------- -----------*/ 68 | #define USBD_MAX_NUM_INTERFACES 1U 69 | /*---------- -----------*/ 70 | #define USBD_MAX_NUM_CONFIGURATION 1U 71 | /*---------- -----------*/ 72 | #define USBD_MAX_STR_DESC_SIZ 512U 73 | /*---------- -----------*/ 74 | #define USBD_DEBUG_LEVEL 1U 75 | /*---------- -----------*/ 76 | #define USBD_LPM_ENABLED 1U 77 | /*---------- -----------*/ 78 | #define USBD_SELF_POWERED 0U 79 | 80 | /****************************************/ 81 | /* #define for FS and HS identification */ 82 | #define DEVICE_FS 0 83 | 84 | /** 85 | * @} 86 | */ 87 | 88 | /** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros 89 | * @brief Aliases. 90 | * @{ 91 | */ 92 | 93 | /* Memory management macros */ 94 | 95 | /** Alias for memory allocation. */ 96 | #define USBD_malloc (void *)USBD_static_malloc 97 | 98 | /** Alias for memory release. */ 99 | #define USBD_free USBD_static_free 100 | 101 | /** Alias for memory set. */ 102 | #define USBD_memset memset 103 | 104 | /** Alias for memory copy. */ 105 | #define USBD_memcpy memcpy 106 | 107 | /** Alias for delay. */ 108 | #define USBD_Delay HAL_Delay 109 | 110 | /* DEBUG macros */ 111 | 112 | #if (USBD_DEBUG_LEVEL > 0) 113 | #define USBD_UsrLog(...) printf(__VA_ARGS__);\ 114 | printf("\n"); 115 | #else 116 | #define USBD_UsrLog(...) 117 | #endif 118 | 119 | #if (USBD_DEBUG_LEVEL > 1) 120 | 121 | #define USBD_ErrLog(...) printf("ERROR: ") ;\ 122 | printf(__VA_ARGS__);\ 123 | printf("\n"); 124 | #else 125 | #define USBD_ErrLog(...) 126 | #endif 127 | 128 | #if (USBD_DEBUG_LEVEL > 2) 129 | #define USBD_DbgLog(...) printf("DEBUG : ") ;\ 130 | printf(__VA_ARGS__);\ 131 | printf("\n"); 132 | #else 133 | #define USBD_DbgLog(...) 134 | #endif 135 | 136 | /** 137 | * @} 138 | */ 139 | 140 | /** @defgroup USBD_CONF_Exported_Types USBD_CONF_Exported_Types 141 | * @brief Types. 142 | * @{ 143 | */ 144 | 145 | /** 146 | * @} 147 | */ 148 | 149 | /** @defgroup USBD_CONF_Exported_FunctionsPrototype USBD_CONF_Exported_FunctionsPrototype 150 | * @brief Declaration of public functions for Usb device. 151 | * @{ 152 | */ 153 | 154 | /* Exported functions -------------------------------------------------------*/ 155 | void *USBD_static_malloc(uint32_t size); 156 | void USBD_static_free(void *p); 157 | 158 | /** 159 | * @} 160 | */ 161 | 162 | /** 163 | * @} 164 | */ 165 | 166 | /** 167 | * @} 168 | */ 169 | 170 | #ifdef __cplusplus 171 | } 172 | #endif 173 | 174 | #endif /* __USBD_CONF__H__ */ 175 | 176 | -------------------------------------------------------------------------------- /firmware/openocd.cfg: -------------------------------------------------------------------------------- 1 | #OpenOCD configuration file, generated by STM32 for VSCode 2 | 3 | # Programmer, can be changed to several interfaces 4 | # Standard will be the stlink interface as this is the standard for STM32 dev boards 5 | source [find interface/stlink.cfg] 6 | 7 | # The target MCU. This should match your board 8 | source [find target/stm32g4x.cfg] 9 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 50x50 Drive 2 | 3 | 4 | This repository contains the firmware, documentation and eventually software/hardware for a low-cost brushless motor controller. 5 | 6 | Visit [the documentation](50x50-drive.readthedocs.io) for more information. 7 | --------------------------------------------------------------------------------