├── Boards ├── disco-h747i │ ├── Asm │ │ └── startup_stm32h747xx.s │ ├── Inc │ │ ├── bsp_ai.h │ │ ├── is42s32800g_conf.h │ │ ├── is42s32800j_conf.h │ │ ├── main.h │ │ ├── mt25tl01g_conf.h │ │ ├── stm32h743i_eval_conf.h │ │ ├── stm32h747i_discovery_conf.h │ │ ├── stm32h7xx_hal_conf.h │ │ └── stm32h7xx_it.h │ ├── STM32H747XIHx_CM7_config1.ld │ ├── STM32H747XIHx_CM7_config4.ld │ ├── Src │ │ ├── main.c │ │ ├── stm32h7xx_hal_msp.c │ │ ├── stm32h7xx_it.c │ │ └── system_stm32h7xx.c │ └── files.mk ├── makefile.disco-h747i ├── makefile.nucleo-f412zg └── nucleo-f412zg │ ├── Asm │ ├── startup_stm32f411retx.s │ └── startup_stm32f412zgtx.s │ ├── Inc │ ├── bsp_ai.h │ ├── main.h │ ├── stm32f4xx_hal_conf.h │ └── stm32f4xx_it.h │ ├── STM32F411RETX_FLASH.ld │ ├── STM32F411RETX_RAM.ld │ ├── STM32F412ZGTX_FLASH.ld │ ├── Src │ ├── main.c │ ├── stm32f4xx_hal_msp.c │ ├── stm32f4xx_it.c │ └── system_stm32f4xx.c │ └── files.mk ├── CONTRIBUTING.md ├── Inc ├── Misc │ ├── aiTestTvmHelper.h │ └── aiTestUtility.h ├── SystemPerformance │ └── aiSystemPerformance.h ├── Validation │ ├── aiPbIO.h │ ├── aiPbMgr.h │ ├── aiValidation.h │ ├── pb.h │ ├── pb_common.h │ ├── pb_decode.h │ ├── pb_encode.h │ └── stm32msg.pb.h ├── ai_platform.h └── app_x-cube-ai.h ├── LICENSE.md ├── Makefile ├── README.md ├── SECURITY.md ├── Src ├── Misc │ ├── aiTestTvmHelper.c │ └── aiTestUtility.c ├── SystemPerformance │ └── aiSystemPerformance.c ├── Validation │ ├── aiPbIO.c │ ├── aiPbMgr.c │ ├── aiValidation.c │ ├── pb_common.c │ ├── pb_decode.c │ ├── pb_encode.c │ └── stm32msg.pb.c ├── app_x-cube-ai.c ├── syscalls.c └── sysmem.c ├── mk ├── common.mk ├── cortex-m33.mk ├── cortex-m4.mk ├── cortex-m7-fpdp.mk ├── cortex-m7.mk ├── default.mk ├── gcc.mk └── macros.mk └── scripts ├── ai_runner ├── __init__.py ├── ai_resolver.py ├── ai_runner.py ├── pb_mgr_drv.py ├── requirements.txt ├── serial_hw_drv.py ├── stm32_utility.py ├── stm32msg_pb2.py └── stm_ai_utils.py ├── compile.py ├── minimal.py ├── mnist_test.py ├── mnist_train.py └── tflite_test.py /Boards/disco-h747i/Inc/bsp_ai.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file bsp_ai.h 15 | * \brief Link to board resources 16 | */ 17 | 18 | #ifndef BSP_H 19 | #define BSP_H 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include "main.h" 25 | #include "stm32h7xx.h" 26 | #include "app_x-cube-ai.h" 27 | #define UartHandle huart1 28 | #define MX_UARTx_Init MX_USART1_UART_Init 29 | void MX_USART1_UART_Init(void); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif /* BSP_H */ 36 | -------------------------------------------------------------------------------- /Boards/disco-h747i/Inc/is42s32800g_conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file is42s32800g_conf.h 15 | * \brief This file contains some configurations required for the 16 | * IS42S32800G SDRAM memory. 17 | */ 18 | 19 | #ifndef IS42S32800G_CONF_H 20 | #define IS42S32800G_CONF_H 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | /* Includes ------------------------------------------------------------------*/ 27 | #include "stm32h7xx_hal.h" 28 | 29 | /** @addtogroup BSP 30 | * @{ 31 | */ 32 | 33 | /** @addtogroup Components 34 | * @{ 35 | */ 36 | 37 | /** @addtogroup IS42S32800G 38 | * @{ 39 | */ 40 | 41 | /** @addtogroup IS42S32800G_Exported_Constants 42 | * @{ 43 | */ 44 | #define REFRESH_COUNT ((uint32_t)0x0603) /* SDRAM refresh counter (100Mhz SD clock) */ 45 | 46 | #define IS42S32800G_TIMEOUT ((uint32_t)0xFFFF) 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* IS42S32800G_CONF_H */ 53 | /** 54 | * @} 55 | */ 56 | 57 | /** 58 | * @} 59 | */ 60 | 61 | /** 62 | * @} 63 | */ 64 | 65 | /** 66 | * @} 67 | */ 68 | -------------------------------------------------------------------------------- /Boards/disco-h747i/Inc/is42s32800j_conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file is42s32800j_conf.h 15 | * \brief This file contains some configurations required for the 16 | * IS42S32800J SDRAM memory. 17 | */ 18 | 19 | #ifndef IS42S32800J_CONF_H 20 | #define IS42S32800J_CONF_H 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | /* Includes ------------------------------------------------------------------*/ 27 | #include "stm32h7xx_hal.h" 28 | 29 | /** @addtogroup BSP 30 | * @{ 31 | */ 32 | 33 | /** @addtogroup Components 34 | * @{ 35 | */ 36 | 37 | /** @addtogroup IS42S32800J 38 | * @{ 39 | */ 40 | 41 | /** @addtogroup IS42S32800J_Exported_Constants 42 | * @{ 43 | */ 44 | #define REFRESH_COUNT ((uint32_t)0x0603) /* SDRAM refresh counter (100Mhz SD clock) */ 45 | 46 | #define IS42S32800J_TIMEOUT ((uint32_t)0xFFFF) 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif /* IS42S32800J_CONF_H */ 53 | /** 54 | * @} 55 | */ 56 | 57 | /** 58 | * @} 59 | */ 60 | 61 | /** 62 | * @} 63 | */ 64 | 65 | /** 66 | * @} 67 | */ 68 | 69 | -------------------------------------------------------------------------------- /Boards/disco-h747i/Inc/main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file main.h 15 | * \brief Header for main.c file. 16 | * This file contains the common defines of the application. 17 | */ 18 | 19 | #ifndef __MAIN_H 20 | #define __MAIN_H 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | /* Includes ------------------------------------------------------------------*/ 27 | #include "stm32h7xx_hal.h" 28 | 29 | /* Private includes ----------------------------------------------------------*/ 30 | /* USER CODE BEGIN Includes */ 31 | 32 | /* USER CODE END Includes */ 33 | 34 | /* Exported types ------------------------------------------------------------*/ 35 | /* USER CODE BEGIN ET */ 36 | 37 | /* USER CODE END ET */ 38 | 39 | /* Exported constants --------------------------------------------------------*/ 40 | /* USER CODE BEGIN EC */ 41 | 42 | /* USER CODE END EC */ 43 | 44 | /* Exported macro ------------------------------------------------------------*/ 45 | /* USER CODE BEGIN EM */ 46 | 47 | /* USER CODE END EM */ 48 | 49 | /* Exported functions prototypes ---------------------------------------------*/ 50 | void Error_Handler(void); 51 | 52 | /* USER CODE BEGIN EFP */ 53 | 54 | /* USER CODE END EFP */ 55 | 56 | /* Private defines -----------------------------------------------------------*/ 57 | void MX_USART1_UART_Init(void); 58 | /* USER CODE BEGIN Private defines */ 59 | 60 | /* USER CODE END Private defines */ 61 | 62 | #ifdef __cplusplus 63 | } 64 | #endif 65 | 66 | #endif /* __MAIN_H */ 67 | -------------------------------------------------------------------------------- /Boards/disco-h747i/Inc/mt25tl01g_conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file mt25tl01g_conf.h 15 | * \brief This file contains all the description of the 16 | * MT25TL01G QSPI memory. 17 | */ 18 | 19 | #ifndef MT25TL01G_CONF_H 20 | #define MT25TL01G_CONF_H 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | /* Includes ------------------------------------------------------------------*/ 27 | #include "stm32h7xx.h" 28 | #include "stm32h7xx_hal.h" 29 | 30 | /** @addtogroup BSP 31 | * @{ 32 | */ 33 | 34 | #define CONF_MT25TL01G_READ_ENHANCE 0 /* MMP performance enhance reade enable/disable */ 35 | 36 | #define CONF_QSPI_ODS MT25TL01G_CR_ODS_15 37 | 38 | #define CONF_QSPI_DUMMY_CLOCK 8U 39 | 40 | /* Dummy cycles for STR read mode */ 41 | #define MT25TL01G_DUMMY_CYCLES_READ_QUAD 8U 42 | #define MT25TL01G_DUMMY_CYCLES_READ 8U 43 | /* Dummy cycles for DTR read mode */ 44 | #define MT25TL01G_DUMMY_CYCLES_READ_DTR 6U 45 | #define MT25TL01G_DUMMY_CYCLES_READ_QUAD_DTR 8U 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | 51 | #endif /* MT25TL01G_CONF_H */ 52 | 53 | /** 54 | * @} 55 | */ 56 | 57 | /** 58 | * @} 59 | */ 60 | 61 | /** 62 | * @} 63 | */ 64 | 65 | -------------------------------------------------------------------------------- /Boards/disco-h747i/Inc/stm32h743i_eval_conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file stm32h743i_eval_conf.h 15 | * \brief STM32h743i_EVAL board configuration file. 16 | */ 17 | 18 | #ifndef STM32h743I_EVAL_CONF_H 19 | #define STM32h743I_EVAL_CONF_H 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /* Includes ------------------------------------------------------------------*/ 26 | #include "stm32h7xx_hal.h" 27 | 28 | /* COM define */ 29 | #define USE_COM_LOG 0U 30 | #define USE_COM_LOG 0U 31 | #define USE_BSP_COM_FEATURE 0U 32 | 33 | /* POT define */ 34 | #define USE_BSP_POT_FEATURE 1U 35 | 36 | /* IO CLASS define */ 37 | #define USE_BSP_IO_CLASS 1U 38 | 39 | /* LCD controllers defines */ 40 | #define USE_DMA2D_TO_FILL_RGB_RECT 0U 41 | #define LCD_LAYER_0_ADDRESS 0xD0000000U 42 | #define LCD_LAYER_1_ADDRESS 0xD0200000U 43 | 44 | /* Audio codecs defines */ 45 | #define USE_AUDIO_CODEC_WM8994 1U 46 | 47 | /* Default Audio IN internal buffer size */ 48 | #define DEFAULT_AUDIO_IN_BUFFER_SIZE 2048U 49 | #define USE_BSP_CPU_CACHE_MAINTENANCE 1U 50 | 51 | /* TS supported features defines */ 52 | #define USE_TS_GESTURE 1U 53 | 54 | /* Default TS touch number */ 55 | #define TS_TOUCH_NBR 2U 56 | 57 | /* Default EEPROM max trials */ 58 | #define EEPROM_MAX_TRIALS 3000U 59 | 60 | /* IRQ priorities */ 61 | #define BSP_SRAM_IT_PRIORITY 15U 62 | #define BSP_SDRAM_IT_PRIORITY 15U 63 | #define BSP_IOEXPANDER_IT_PRIORITY 15U 64 | #define BSP_BUTTON_USER_IT_PRIORITY 15U 65 | #define BSP_BUTTON_WAKEUP_IT_PRIORITY 15U 66 | #define BSP_BUTTON_TAMPER_IT_PRIORITY 15U 67 | #define BSP_AUDIO_OUT_IT_PRIORITY 14U 68 | #define BSP_AUDIO_IN_IT_PRIORITY 15U 69 | #define BSP_SD_IT_PRIORITY 14U 70 | #define BSP_SD_RX_IT_PRIORITY 14U 71 | #define BSP_SD_TX_IT_PRIORITY 15U 72 | #define BSP_TS_IT_PRIORITY 15U 73 | 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | 78 | #endif /* STM32h743I_EVAL_CONF_H */ 79 | -------------------------------------------------------------------------------- /Boards/disco-h747i/Inc/stm32h747i_discovery_conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file stm32h747i_discovery_conf.h 15 | * \brief STM32H747I_Discovery board configuration file. 16 | */ 17 | 18 | #ifndef STM32H747I_DISCO_CONF_H 19 | #define STM32H747I_DISCO_CONF_H 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /* Includes ------------------------------------------------------------------*/ 26 | #include "stm32h7xx_hal.h" 27 | 28 | /* COM define */ 29 | #define USE_COM_LOG 0U 30 | #define USE_BSP_COM_FEATURE 0U 31 | 32 | /* LCD controllers defines */ 33 | #define USE_LCD_CTRL_OTM8009A 1U 34 | #define USE_LCD_CTRL_ADV7533 1U 35 | 36 | #define LCD_LAYER_0_ADDRESS 0xD0000000U 37 | #define LCD_LAYER_1_ADDRESS 0xD0200000U 38 | 39 | #define USE_DMA2D_TO_FILL_RGB_RECT 0U 40 | /* Camera sensors defines */ 41 | #define USE_CAMERA_SENSOR_OV5640 1U 42 | #define USE_CAMERA_SENSOR_S5K5CAG 1U 43 | /* Audio codecs defines */ 44 | #define USE_AUDIO_CODEC_WM8994 1U 45 | 46 | /* Default Audio IN internal buffer size */ 47 | #define DEFAULT_AUDIO_IN_BUFFER_SIZE 64U 48 | /* TS supported features defines */ 49 | #define USE_TS_GESTURE 1U 50 | #define USE_TS_MULTI_TOUCH 1U 51 | 52 | /* Default TS touch number */ 53 | #define TS_TOUCH_NBR 2U 54 | #define CAMERA_FRAME_BUFFER ((uint32_t)0xD0600000) 55 | 56 | /* IRQ priorities */ 57 | #define BSP_SDRAM_IT_PRIORITY 15U 58 | #define BSP_CAMERA_IT_PRIORITY 15U 59 | #define BSP_BUTTON_WAKEUP_IT_PRIORITY 15U 60 | #define BSP_AUDIO_OUT_IT_PRIORITY 14U 61 | #define BSP_AUDIO_IN_IT_PRIORITY 15U 62 | #define BSP_SD_IT_PRIORITY 14U 63 | #define BSP_SD_RX_IT_PRIORITY 14U 64 | #define BSP_SD_TX_IT_PRIORITY 15U 65 | #define BSP_TS_IT_PRIORITY 15U 66 | #define BSP_JOY1_SEL_IT_PRIORITY 15U 67 | #define BSP_JOY1_DOWN_IT_PRIORITY 15U 68 | #define BSP_JOY1_LEFT_IT_PRIORITY 15U 69 | #define BSP_JOY1_RIGHT_IT_PRIORITY 15U 70 | #define BSP_JOY1_UP_IT_PRIORITY 15U 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif /* STM32H747I_DISCO_CONF_H */ 77 | -------------------------------------------------------------------------------- /Boards/disco-h747i/Inc/stm32h7xx_it.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file stm32h7xx_it.h 15 | * \brief This file contains the headers of the interrupt handlers. 16 | */ 17 | 18 | #ifndef __STM32H7xx_IT_H 19 | #define __STM32H7xx_IT_H 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /* Private includes ----------------------------------------------------------*/ 26 | /* USER CODE BEGIN Includes */ 27 | 28 | /* USER CODE END Includes */ 29 | 30 | /* Exported types ------------------------------------------------------------*/ 31 | /* USER CODE BEGIN ET */ 32 | 33 | /* USER CODE END ET */ 34 | 35 | /* Exported constants --------------------------------------------------------*/ 36 | /* USER CODE BEGIN EC */ 37 | 38 | /* USER CODE END EC */ 39 | 40 | /* Exported macro ------------------------------------------------------------*/ 41 | /* USER CODE BEGIN EM */ 42 | 43 | /* USER CODE END EM */ 44 | 45 | /* Exported functions prototypes ---------------------------------------------*/ 46 | void NMI_Handler(void); 47 | void HardFault_Handler(void); 48 | void MemManage_Handler(void); 49 | void BusFault_Handler(void); 50 | void UsageFault_Handler(void); 51 | void SVC_Handler(void); 52 | void DebugMon_Handler(void); 53 | void PendSV_Handler(void); 54 | void SysTick_Handler(void); 55 | /* USER CODE BEGIN EFP */ 56 | 57 | /* USER CODE END EFP */ 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif /* __STM32H7xx_IT_H */ 64 | -------------------------------------------------------------------------------- /Boards/disco-h747i/STM32H747XIHx_CM7_config1.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /* 14 | * Linker script for STM32H7 series 15 | * 1024Kbytes FLASH and 192Kbytes RAM 16 | * 17 | * Set heap size, stack size and stack location according 18 | * to application requirements. 19 | * 20 | * Set memory bank area and size if external memory is used. 21 | * 22 | * Target : STMicroelectronics STM32 23 | */ 24 | 25 | /* Entry Point */ 26 | ENTRY(Reset_Handler) 27 | 28 | _Min_Heap_Size = 0x12000; /* required amount of heap */ 29 | _Min_Stack_Size = 0x8000; /* required amount of stack */ 30 | 31 | /* Specify the memory areas */ 32 | MEMORY 33 | { 34 | ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K 35 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K 36 | DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K 37 | AXIRAM (xrw) : ORIGIN = 0x24000000, LENGTH = 512K 38 | SRAM123 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K 39 | SRAM4 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K 40 | BKPSRAM (xrw) : ORIGIN = 0x38800000, LENGTH = 64K 41 | QSPIFLASH (rx) : ORIGIN = 0x90000000, LENGTH = 128M 42 | SDRAM (xrw) : ORIGIN = 0xD0000000, LENGTH = 32M 43 | } 44 | 45 | /* Define output sections */ 46 | SECTIONS 47 | { 48 | /* The startup code goes first into FLASH */ 49 | .isr_vector : 50 | { 51 | . = ALIGN(4); 52 | KEEP(*(.isr_vector)) /* Startup code */ 53 | . = ALIGN(4); 54 | } >FLASH 55 | 56 | /* The program code and other data goes into FLASH */ 57 | .text : 58 | { 59 | . = ALIGN(4); 60 | *(.text) /* .text sections (code) */ 61 | *(.text*) /* .text* sections (code) */ 62 | *(.glue_7) /* glue arm to thumb code */ 63 | *(.glue_7t) /* glue thumb to arm code */ 64 | *(.eh_frame) 65 | 66 | KEEP (*(.init)) 67 | KEEP (*(.fini)) 68 | 69 | . = ALIGN(4); 70 | _etext = .; /* define a global symbols at end of code */ 71 | } >FLASH 72 | 73 | /* Constant data goes into FLASH */ 74 | .rodata : 75 | { 76 | . = ALIGN(4); 77 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 78 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 79 | . = ALIGN(4); 80 | } >FLASH 81 | 82 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH 83 | .ARM : { 84 | __exidx_start = .; 85 | *(.ARM.exidx*) 86 | __exidx_end = .; 87 | } >FLASH 88 | 89 | .preinit_array : 90 | { 91 | PROVIDE_HIDDEN (__preinit_array_start = .); 92 | KEEP (*(.preinit_array*)) 93 | PROVIDE_HIDDEN (__preinit_array_end = .); 94 | } >FLASH 95 | .init_array : 96 | { 97 | PROVIDE_HIDDEN (__init_array_start = .); 98 | KEEP (*(SORT(.init_array.*))) 99 | KEEP (*(.init_array*)) 100 | PROVIDE_HIDDEN (__init_array_end = .); 101 | } >FLASH 102 | .fini_array : 103 | { 104 | PROVIDE_HIDDEN (__fini_array_start = .); 105 | KEEP (*(SORT(.fini_array.*))) 106 | KEEP (*(.fini_array*)) 107 | PROVIDE_HIDDEN (__fini_array_end = .); 108 | } >FLASH 109 | 110 | .nn_models : 111 | { 112 | . = ALIGN(4); 113 | __models_section_start__ = .; 114 | KEEP (*(.nn_models*)) 115 | __models_section_end__ = .; 116 | } >FLASH 117 | 118 | /* used by the startup to initialize data */ 119 | _sidata = LOADADDR(.data); 120 | 121 | /* Initialized data sections goes into RAM, load LMA copy after code */ 122 | .data : 123 | { 124 | . = ALIGN(4); 125 | _sdata = .; /* create a global symbol at data start */ 126 | *(.data) /* .data sections */ 127 | *(.data*) /* .data* sections */ 128 | 129 | . = ALIGN(4); 130 | _edata = .; /* define a global symbol at data end */ 131 | } >DTCMRAM AT> FLASH 132 | 133 | 134 | /* Uninitialized data section */ 135 | . = ALIGN(4); 136 | .bss : 137 | { 138 | /* This is used by the startup in order to initialize the .bss secion */ 139 | _sbss = .; /* define a global symbol at bss start */ 140 | __bss_start__ = _sbss; 141 | *(.bss) 142 | *(.bss*) 143 | *(COMMON) 144 | 145 | . = ALIGN(4); 146 | _ebss = .; /* define a global symbol at bss end */ 147 | __bss_end__ = _ebss; 148 | } >DTCMRAM 149 | 150 | /* User_heap_stack section, used to check that there is enough "RAM" type memory left */ 151 | ._user_heap_stack : 152 | { 153 | . = ALIGN(8); 154 | PROVIDE ( end = . ); 155 | PROVIDE ( _end = . ); 156 | . = . + _Min_Heap_Size; 157 | _sstack = .; 158 | . = . + _Min_Stack_Size; 159 | _estack = .; 160 | . = ALIGN(8); 161 | } >DTCMRAM 162 | 163 | .params : 164 | { 165 | *(.nn_weights*) 166 | } >FLASH 167 | 168 | .nn_data (NOLOAD) : 169 | { 170 | *. = ORIGIN(AXIRAM); 171 | *(*.nn_data_act) 172 | *(.nn_data) 173 | *(.nn_data*) 174 | . = ALIGN(4); 175 | } >AXIRAM 176 | 177 | /* Remove information from the standard libraries */ 178 | /DISCARD/ : 179 | { 180 | libc.a ( * ) 181 | libm.a ( * ) 182 | libgcc.a ( * ) 183 | } 184 | 185 | .ARM.attributes 0 : { *(.ARM.attributes) } 186 | } 187 | 188 | 189 | -------------------------------------------------------------------------------- /Boards/disco-h747i/STM32H747XIHx_CM7_config4.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /* 14 | * Linker script for STM32H7 series 15 | * 1024Kbytes FLASH and 192Kbytes RAM 16 | * 17 | * Set heap size, stack size and stack location according 18 | * to application requirements. 19 | * 20 | * Set memory bank area and size if external memory is used. 21 | * 22 | * Target : STMicroelectronics STM32 23 | */ 24 | 25 | /* Entry Point */ 26 | ENTRY(Reset_Handler) 27 | 28 | /* Highest address of the user mode stack */ 29 | /* _estack = 0x24080000; */ /* end of AXIRAM */ 30 | /*_estack = 0x20020000; */ /* end of DTCMRAM */ 31 | /* Generate a link error if heap and stack don't fit into RAM */ 32 | /* _Min_Heap_Size = 0x100000; */ /* 1MB 0x4000; */ /* required amount of heap */ 33 | _Min_Heap_Size = 0x40000; /* 256KB */ 34 | _Min_Stack_Size = 0x8000; /* required amount of stack */ 35 | 36 | /* Specify the memory areas */ 37 | MEMORY 38 | { 39 | ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K 40 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K 41 | DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K 42 | AXIRAM (xrw) : ORIGIN = 0x24000000, LENGTH = 512K 43 | SRAM123 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K 44 | SRAM4 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K 45 | BKPSRAM (xrw) : ORIGIN = 0x38800000, LENGTH = 64K 46 | QSPIFLASH (rx) : ORIGIN = 0x90000000, LENGTH = 128M 47 | SDRAM (xrw) : ORIGIN = 0xD0000000, LENGTH = 32M 48 | } 49 | 50 | /* Define output sections */ 51 | SECTIONS 52 | { 53 | /* The startup code goes first into FLASH */ 54 | .isr_vector : 55 | { 56 | . = ALIGN(4); 57 | KEEP(*(.isr_vector)) /* Startup code */ 58 | . = ALIGN(4); 59 | } >FLASH 60 | 61 | 62 | /* The program code and other data goes into FLASH */ 63 | .text : 64 | { 65 | . = ALIGN(4); 66 | *(.text) /* .text sections (code) */ 67 | *(.text*) /* .text* sections (code) */ 68 | *(.glue_7) /* glue arm to thumb code */ 69 | *(.glue_7t) /* glue thumb to arm code */ 70 | *(.eh_frame) 71 | 72 | KEEP (*(.init)) 73 | KEEP (*(.fini)) 74 | 75 | . = ALIGN(4); 76 | _etext = .; /* define a global symbols at end of code */ 77 | } >FLASH 78 | 79 | /* Constant data goes into FLASH */ 80 | .rodata : 81 | { 82 | . = ALIGN(4); 83 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 84 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 85 | . = ALIGN(4); 86 | } >FLASH 87 | 88 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH 89 | .ARM : { 90 | __exidx_start = .; 91 | *(.ARM.exidx*) 92 | __exidx_end = .; 93 | } >FLASH 94 | 95 | .preinit_array : 96 | { 97 | PROVIDE_HIDDEN (__preinit_array_start = .); 98 | KEEP (*(.preinit_array*)) 99 | PROVIDE_HIDDEN (__preinit_array_end = .); 100 | } >FLASH 101 | .init_array : 102 | { 103 | PROVIDE_HIDDEN (__init_array_start = .); 104 | KEEP (*(SORT(.init_array.*))) 105 | KEEP (*(.init_array*)) 106 | PROVIDE_HIDDEN (__init_array_end = .); 107 | } >FLASH 108 | .fini_array : 109 | { 110 | PROVIDE_HIDDEN (__fini_array_start = .); 111 | KEEP (*(SORT(.fini_array.*))) 112 | KEEP (*(.fini_array*)) 113 | PROVIDE_HIDDEN (__fini_array_end = .); 114 | } >FLASH 115 | 116 | .nn_models : 117 | { 118 | . = ALIGN(4); 119 | __models_section_start__ = .; 120 | KEEP (*(.nn_models*)) 121 | __models_section_end__ = .; 122 | } >FLASH 123 | 124 | /* User_heap_stack section, used to check that there is enough RAM left */ 125 | ._user_stack : 126 | { 127 | . = ALIGN(8); 128 | _sstack = .; 129 | . = . + _Min_Stack_Size; 130 | _estack = .; 131 | . = ALIGN(8); 132 | } >DTCMRAM /* AXIRAM DTCMRAM*/ 133 | 134 | /* Check if MY_MEMORY usage exceeds MY_MEMORY size */ 135 | /* 136 | ASSERT( LENGTH(MY_MEMORY) >= (__mysection_end__ - __mysection_start__), "MY_MEMORY memory overflowed !") 137 | */ 138 | 139 | /* used by the startup to initialize data */ 140 | _sidata = LOADADDR(.data); 141 | 142 | /* Initialized data sections goes into RAM, load LMA copy after code */ 143 | .data : 144 | { 145 | . = ALIGN(4); 146 | _sdata = .; /* create a global symbol at data start */ 147 | *(.data) /* .data sections */ 148 | *(.data*) /* .data* sections */ 149 | 150 | . = ALIGN(4); 151 | _edata = .; /* define a global symbol at data end */ 152 | } >DTCMRAM AT> FLASH 153 | 154 | 155 | /* Uninitialized data section */ 156 | . = ALIGN(4); 157 | .bss : 158 | { 159 | /* This is used by the startup in order to initialize the .bss secion */ 160 | _sbss = .; /* define a global symbol at bss start */ 161 | __bss_start__ = _sbss; 162 | *(.bss) 163 | *(.bss*) 164 | *(COMMON) 165 | 166 | . = ALIGN(4); 167 | _ebss = .; /* define a global symbol at bss end */ 168 | __bss_end__ = _ebss; 169 | } >DTCMRAM 170 | 171 | /* Warning: looks like there is no heap overlow check in sbrk */ 172 | ._user_heap : 173 | { 174 | . = ALIGN(8); 175 | PROVIDE ( end = . ); 176 | PROVIDE ( _end = . ); 177 | . = . + _Min_Heap_Size; 178 | __HeapLimit = .; 179 | . = ALIGN(8); 180 | } >SDRAM /* >SDRAM AXIRAM */ 181 | 182 | .params_external_flash : 183 | { 184 | *(.nn_weights*) 185 | } >QSPIFLASH /* QSPIFLASH FLASH*/ 186 | 187 | .external_sdram (NOLOAD) : 188 | { 189 | *(*.nn_data_act) 190 | /**(.nn_data*)*/ 191 | } >SDRAM /*> SDRAM */ /* >AXIRAM*/ /* DTCMRAM */ 192 | 193 | /* Remove information from the standard libraries */ 194 | /DISCARD/ : 195 | { 196 | libc.a ( * ) 197 | libm.a ( * ) 198 | libgcc.a ( * ) 199 | } 200 | 201 | .ARM.attributes 0 : { *(.ARM.attributes) } 202 | } 203 | 204 | 205 | -------------------------------------------------------------------------------- /Boards/disco-h747i/Src/stm32h7xx_hal_msp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file stm32h7xx_hal_msp.c 15 | * \brief This file provides code for the MSP Initialization 16 | * and de-Initialization codes. 17 | */ 18 | 19 | /* Includes ------------------------------------------------------------------*/ 20 | #include "main.h" 21 | /* USER CODE BEGIN Includes */ 22 | 23 | /* USER CODE END Includes */ 24 | 25 | /* Private typedef -----------------------------------------------------------*/ 26 | /* USER CODE BEGIN TD */ 27 | 28 | /* USER CODE END TD */ 29 | 30 | /* Private define ------------------------------------------------------------*/ 31 | /* USER CODE BEGIN Define */ 32 | 33 | /* USER CODE END Define */ 34 | 35 | /* Private macro -------------------------------------------------------------*/ 36 | /* USER CODE BEGIN Macro */ 37 | 38 | /* USER CODE END Macro */ 39 | 40 | /* Private variables ---------------------------------------------------------*/ 41 | /* USER CODE BEGIN PV */ 42 | 43 | /* USER CODE END PV */ 44 | 45 | /* Private function prototypes -----------------------------------------------*/ 46 | /* USER CODE BEGIN PFP */ 47 | 48 | /* USER CODE END PFP */ 49 | 50 | /* External functions --------------------------------------------------------*/ 51 | /* USER CODE BEGIN ExternalFunctions */ 52 | 53 | /* USER CODE END ExternalFunctions */ 54 | 55 | /* USER CODE BEGIN 0 */ 56 | 57 | /* USER CODE END 0 */ 58 | /** 59 | * Initializes the Global MSP. 60 | */ 61 | void HAL_MspInit(void) 62 | { 63 | /* USER CODE BEGIN MspInit 0 */ 64 | 65 | /* USER CODE END MspInit 0 */ 66 | 67 | __HAL_RCC_SYSCFG_CLK_ENABLE(); 68 | 69 | /* System interrupt init*/ 70 | 71 | /* USER CODE BEGIN MspInit 1 */ 72 | 73 | /* USER CODE END MspInit 1 */ 74 | } 75 | 76 | /** 77 | * @brief CRC MSP Initialization 78 | * This function configures the hardware resources used in this example 79 | * @param hcrc: CRC handle pointer 80 | * @retval None 81 | */ 82 | void HAL_CRC_MspInit(CRC_HandleTypeDef* hcrc) 83 | { 84 | if(hcrc->Instance==CRC) 85 | { 86 | /* USER CODE BEGIN CRC_MspInit 0 */ 87 | 88 | /* USER CODE END CRC_MspInit 0 */ 89 | /* Peripheral clock enable */ 90 | __HAL_RCC_CRC_CLK_ENABLE(); 91 | /* USER CODE BEGIN CRC_MspInit 1 */ 92 | 93 | /* USER CODE END CRC_MspInit 1 */ 94 | } 95 | 96 | } 97 | 98 | /** 99 | * @brief CRC MSP De-Initialization 100 | * This function freeze the hardware resources used in this example 101 | * @param hcrc: CRC handle pointer 102 | * @retval None 103 | */ 104 | void HAL_CRC_MspDeInit(CRC_HandleTypeDef* hcrc) 105 | { 106 | if(hcrc->Instance==CRC) 107 | { 108 | /* USER CODE BEGIN CRC_MspDeInit 0 */ 109 | 110 | /* USER CODE END CRC_MspDeInit 0 */ 111 | /* Peripheral clock disable */ 112 | __HAL_RCC_CRC_CLK_DISABLE(); 113 | /* USER CODE BEGIN CRC_MspDeInit 1 */ 114 | 115 | /* USER CODE END CRC_MspDeInit 1 */ 116 | } 117 | 118 | } 119 | 120 | /** 121 | * @brief UART MSP Initialization 122 | * This function configures the hardware resources used in this example 123 | * @param huart: UART handle pointer 124 | * @retval None 125 | */ 126 | void HAL_UART_MspInit(UART_HandleTypeDef* huart) 127 | { 128 | GPIO_InitTypeDef GPIO_InitStruct = {0}; 129 | if(huart->Instance==USART1) 130 | { 131 | /* USER CODE BEGIN USART1_MspInit 0 */ 132 | 133 | /* USER CODE END USART1_MspInit 0 */ 134 | /* Peripheral clock enable */ 135 | __HAL_RCC_USART1_CLK_ENABLE(); 136 | 137 | 138 | #if defined(USE_STM32H747I_DISCO) 139 | __HAL_RCC_GPIOA_CLK_ENABLE(); 140 | 141 | /**USART1 GPIO Configuration 142 | PA9 ------> USART1_TX 143 | PA10 ------> USART1_RX 144 | */ 145 | GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; 146 | GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 147 | // GPIO_InitStruct.Pull = GPIO_NOPULL; 148 | GPIO_InitStruct.Pull = GPIO_PULLUP; 149 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 150 | GPIO_InitStruct.Alternate = GPIO_AF7_USART1; 151 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 152 | 153 | #elif defined(USE_STM32H743I_EVAL) 154 | __HAL_RCC_GPIOB_CLK_ENABLE(); 155 | 156 | /**USART1 GPIO Configuration 157 | PB15 ------> USART1_RX 158 | PB14 ------> USART1_TX 159 | */ 160 | GPIO_InitStruct.Pin = GPIO_PIN_14 | GPIO_PIN_15; 161 | GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 162 | GPIO_InitStruct.Pull = GPIO_NOPULL; 163 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 164 | GPIO_InitStruct.Alternate = GPIO_AF4_USART1; 165 | HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 166 | #else 167 | #error "Define board" 168 | #endif 169 | 170 | 171 | /* USER CODE BEGIN USART1_MspInit 1 */ 172 | 173 | /* USER CODE END USART1_MspInit 1 */ 174 | } 175 | 176 | } 177 | 178 | /** 179 | * @brief UART MSP De-Initialization 180 | * This function freeze the hardware resources used in this example 181 | * @param huart: UART handle pointer 182 | * @retval None 183 | */ 184 | void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) 185 | { 186 | if(huart->Instance==USART1) 187 | { 188 | /* USER CODE BEGIN USART1_MspDeInit 0 */ 189 | 190 | /* USER CODE END USART1_MspDeInit 0 */ 191 | /* Peripheral clock disable */ 192 | __HAL_RCC_USART1_CLK_DISABLE(); 193 | 194 | #if defined(USE_STM32H747I_DISCO) 195 | /**USART1 GPIO Configuration 196 | PA9 ------> USART1_TX 197 | PA10 ------> USART1_RX 198 | */ 199 | HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); 200 | #elif defined(USE_STM32H743I_EVAL) 201 | /**USART1 GPIO Configuration 202 | PB15 ------> USART1_RX 203 | PB14 ------> USART1_TX 204 | */ 205 | HAL_GPIO_DeInit(GPIOB, GPIO_PIN_14|GPIO_PIN_15); 206 | #else 207 | #error "Define board" 208 | #endif 209 | /* USER CODE BEGIN USART1_MspDeInit 1 */ 210 | 211 | /* USER CODE END USART1_MspDeInit 1 */ 212 | } 213 | 214 | } 215 | 216 | /* USER CODE BEGIN 1 */ 217 | 218 | /* USER CODE END 1 */ 219 | 220 | 221 | -------------------------------------------------------------------------------- /Boards/disco-h747i/Src/stm32h7xx_it.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file stm32h7xx_it.c 15 | * \brief Interrupt Service Routines. 16 | */ 17 | 18 | #include "main.h" 19 | #include "stm32h7xx_it.h" 20 | /* Private includes ----------------------------------------------------------*/ 21 | /* USER CODE BEGIN Includes */ 22 | /* USER CODE END Includes */ 23 | 24 | /* Private typedef -----------------------------------------------------------*/ 25 | /* USER CODE BEGIN TD */ 26 | 27 | /* USER CODE END TD */ 28 | 29 | /* Private define ------------------------------------------------------------*/ 30 | /* USER CODE BEGIN PD */ 31 | 32 | /* USER CODE END PD */ 33 | 34 | /* Private macro -------------------------------------------------------------*/ 35 | /* USER CODE BEGIN PM */ 36 | 37 | /* USER CODE END PM */ 38 | 39 | /* Private variables ---------------------------------------------------------*/ 40 | /* USER CODE BEGIN PV */ 41 | 42 | /* USER CODE END PV */ 43 | 44 | /* Private function prototypes -----------------------------------------------*/ 45 | /* USER CODE BEGIN PFP */ 46 | 47 | /* USER CODE END PFP */ 48 | 49 | /* Private user code ---------------------------------------------------------*/ 50 | /* USER CODE BEGIN 0 */ 51 | 52 | /* USER CODE END 0 */ 53 | 54 | /* External variables --------------------------------------------------------*/ 55 | 56 | /* USER CODE BEGIN EV */ 57 | 58 | /* USER CODE END EV */ 59 | 60 | /******************************************************************************/ 61 | /* Cortex Processor Interruption and Exception Handlers */ 62 | /******************************************************************************/ 63 | /** 64 | * @brief This function handles Non maskable interrupt. 65 | */ 66 | void NMI_Handler(void) 67 | { 68 | /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ 69 | 70 | /* USER CODE END NonMaskableInt_IRQn 0 */ 71 | /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ 72 | 73 | /* USER CODE END NonMaskableInt_IRQn 1 */ 74 | } 75 | 76 | /** 77 | * @brief This function handles Hard fault interrupt. 78 | */ 79 | void HardFault_Handler(void) 80 | { 81 | /* USER CODE BEGIN HardFault_IRQn 0 */ 82 | 83 | /* USER CODE END HardFault_IRQn 0 */ 84 | while (1) 85 | { 86 | /* USER CODE BEGIN W1_HardFault_IRQn 0 */ 87 | /* USER CODE END W1_HardFault_IRQn 0 */ 88 | } 89 | } 90 | 91 | /** 92 | * @brief This function handles Memory management fault. 93 | */ 94 | void MemManage_Handler(void) 95 | { 96 | /* USER CODE BEGIN MemoryManagement_IRQn 0 */ 97 | 98 | /* USER CODE END MemoryManagement_IRQn 0 */ 99 | while (1) 100 | { 101 | /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ 102 | /* USER CODE END W1_MemoryManagement_IRQn 0 */ 103 | } 104 | } 105 | 106 | /** 107 | * @brief This function handles Pre-fetch fault, memory access fault. 108 | */ 109 | void BusFault_Handler(void) 110 | { 111 | /* USER CODE BEGIN BusFault_IRQn 0 */ 112 | 113 | /* USER CODE END BusFault_IRQn 0 */ 114 | while (1) 115 | { 116 | /* USER CODE BEGIN W1_BusFault_IRQn 0 */ 117 | /* USER CODE END W1_BusFault_IRQn 0 */ 118 | } 119 | } 120 | 121 | /** 122 | * @brief This function handles Undefined instruction or illegal state. 123 | */ 124 | void UsageFault_Handler(void) 125 | { 126 | /* USER CODE BEGIN UsageFault_IRQn 0 */ 127 | 128 | /* USER CODE END UsageFault_IRQn 0 */ 129 | while (1) 130 | { 131 | /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ 132 | /* USER CODE END W1_UsageFault_IRQn 0 */ 133 | } 134 | } 135 | 136 | /** 137 | * @brief This function handles System service call via SWI instruction. 138 | */ 139 | void SVC_Handler(void) 140 | { 141 | /* USER CODE BEGIN SVCall_IRQn 0 */ 142 | 143 | /* USER CODE END SVCall_IRQn 0 */ 144 | /* USER CODE BEGIN SVCall_IRQn 1 */ 145 | 146 | /* USER CODE END SVCall_IRQn 1 */ 147 | } 148 | 149 | /** 150 | * @brief This function handles Debug monitor. 151 | */ 152 | void DebugMon_Handler(void) 153 | { 154 | /* USER CODE BEGIN DebugMonitor_IRQn 0 */ 155 | 156 | /* USER CODE END DebugMonitor_IRQn 0 */ 157 | /* USER CODE BEGIN DebugMonitor_IRQn 1 */ 158 | 159 | /* USER CODE END DebugMonitor_IRQn 1 */ 160 | } 161 | 162 | /** 163 | * @brief This function handles Pendable request for system service. 164 | */ 165 | void PendSV_Handler(void) 166 | { 167 | /* USER CODE BEGIN PendSV_IRQn 0 */ 168 | 169 | /* USER CODE END PendSV_IRQn 0 */ 170 | /* USER CODE BEGIN PendSV_IRQn 1 */ 171 | 172 | /* USER CODE END PendSV_IRQn 1 */ 173 | } 174 | 175 | /** 176 | * @brief This function handles System tick timer. 177 | */ 178 | void SysTick_Handler(void) 179 | { 180 | /* USER CODE BEGIN SysTick_IRQn 0 */ 181 | 182 | /* USER CODE END SysTick_IRQn 0 */ 183 | HAL_IncTick(); 184 | /* USER CODE BEGIN SysTick_IRQn 1 */ 185 | 186 | /* USER CODE END SysTick_IRQn 1 */ 187 | } 188 | 189 | /******************************************************************************/ 190 | /* STM32H7xx Peripheral Interrupt Handlers */ 191 | /* Add here the Interrupt Handlers for the used peripherals. */ 192 | /* For the available peripheral interrupt handler names, */ 193 | /* please refer to the startup file (startup_stm32h7xx.s). */ 194 | /******************************************************************************/ 195 | 196 | /* USER CODE BEGIN 1 */ 197 | 198 | /* USER CODE END 1 */ 199 | -------------------------------------------------------------------------------- /Boards/disco-h747i/files.mk: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | # Source files specific for this target 13 | 14 | # 15 | # Application C sources 16 | # 17 | C_SRC_APP += ${BOARDS_DIR}/${BOARD}/Src/main.c 18 | C_SRC_APP += ${BOARDS_DIR}/${BOARD}/Src/stm32h7xx_hal_msp.c 19 | C_SRC_APP += ${BOARDS_DIR}/${BOARD}/Src/stm32h7xx_it.c 20 | C_SRC_APP += ${BOARDS_DIR}/${BOARD}/Src/system_stm32h7xx.c 21 | 22 | CFLAGS += -DUSE_HAL_DRIVER 23 | 24 | # Startup file 25 | ASM_SRC_APP += ${BOARDS_DIR}/${BOARD}/Asm/startup_stm32h747xx.s 26 | 27 | # HAL 28 | 29 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal.c 30 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_cortex.c 31 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_crc.c 32 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_crc_ex.c 33 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_dma.c 34 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_dma_ex.c 35 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_eth.c 36 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_exti.c 37 | 38 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_flash.c 39 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_flash_ex.c 40 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_gpio.c 41 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_hsem.c 42 | 43 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_i2c.c 44 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_i2c_ex.c 45 | 46 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_mdma.c 47 | 48 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_pcd.c 49 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_pcd_ex.c 50 | 51 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_pwr.c 52 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_pwr_ex.c 53 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_qspi.c 54 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_rcc.c 55 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_rcc_ex.c 56 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_sdram.c 57 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_tim.c 58 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_tim_ex.c 59 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_uart.c 60 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_hal_uart_ex.c 61 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_ll_usb.c 62 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32h7xx_ll_fmc.c 63 | 64 | CFLAGS += -I${HAL_DIR_ROOT}/Inc 65 | 66 | # BSP 67 | 68 | C_SRC_BSP += ${BSP_DIR_ROOT}/Components/is42s32800j/is42s32800j.c 69 | C_SRC_BSP += ${BSP_DIR_ROOT}/Components/mfxstm32l152/mfxstm32l152.c 70 | C_SRC_BSP += ${BSP_DIR_ROOT}/Components/mfxstm32l152/mfxstm32l152_reg.c 71 | C_SRC_BSP += ${BSP_DIR_ROOT}/Components/mt25tl01g/mt25tl01g.c 72 | 73 | C_SRC_BSP += ${BSP_DIR_ROOT}/STM32H747I-DISCO/stm32h747i_discovery.c 74 | C_SRC_BSP += ${BSP_DIR_ROOT}/STM32H747I-DISCO/stm32h747i_discovery_sdram.c 75 | C_SRC_BSP += ${BSP_DIR_ROOT}/STM32H747I-DISCO/stm32h747i_discovery_qspi.c 76 | 77 | CFLAGS += -I${BSP_DIR_ROOT}/STM32H747I-DISCO 78 | CFLAGS += -I${BSP_DIR_ROOT}/Components/mt25tl01g 79 | 80 | C_SOURCES += ${C_SRC_APP} ${C_SRC_HAL} ${C_SRC_BSP} 81 | ASM_SOURCES += ${ASM_SRC_APP} 82 | -------------------------------------------------------------------------------- /Boards/makefile.disco-h747i: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | # Makefile for the STM32 H747 Disco project. 13 | 14 | ROOT_DIR ?= . 15 | BOARDS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) 16 | 17 | BOARD = disco-h747i 18 | 19 | # 20 | # Default options 21 | # 22 | include mk/default.mk 23 | 24 | # 25 | # TOOLS ----------------------------------------------------------- 26 | # 27 | include mk/gcc.mk 28 | include mk/macros.mk 29 | 30 | # 31 | # Core/Device options --------------------------------------------- 32 | # 33 | CORE := 34 | 35 | STM32 := STM32H7xx 36 | DEVICE := STM32H747xx 37 | DEVICE_CORE := cortex-m7-fpdp 38 | 39 | include mk/$(DEVICE_CORE).mk 40 | 41 | CFLAGS-${CORE} += -D${DEVICE} -DCORE_CM7 42 | 43 | CFLAGS += -DUSE_STM32H747I_DISCO 44 | CFLAGS += -DUSE_QSPI_CLK_90MHZ=0 45 | # CFLAGS += -DUSE_VOS0_480MHZ_OVERCLOCK=1 46 | CFLAGS += -DUSE_WEIGHTS_IN_SDRAM=0 47 | 48 | # Indicate the used configuration memory (1: all in internal) 49 | USE_CONFIG_MEM ?= 4 50 | 51 | ifeq ($(strip $(USE_CONFIG_MEM)),1) 52 | LDSCRIPTS ?= $(BOARDS_DIR)/$(BOARD)/STM32H747XIHx_CM7_config1.ld 53 | endif 54 | 55 | ifeq ($(strip $(USE_CONFIG_MEM)),4) 56 | LDSCRIPTS ?= $(BOARDS_DIR)/$(BOARD)/STM32H747XIHx_CM7_config4.ld 57 | endif 58 | 59 | ifeq ($(strip $(LDSCRIPTS)),) 60 | $(error No LDSCRIPT is defined for the disco-h747i - supported USE_CONFIG_MEM = 1 or 4) 61 | endif 62 | 63 | LDFLAGS += $(LDFLAGS-$(CORE)) 64 | LDFLAGS += -T$(LDSCRIPTS) 65 | 66 | include mk/common.mk 67 | -------------------------------------------------------------------------------- /Boards/makefile.nucleo-f412zg: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | # Makefile for the STM32 F412 Disco project. 13 | 14 | ROOT_DIR ?= . 15 | BOARDS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) 16 | 17 | BOARD = nucleo-f412zg 18 | 19 | # 20 | # Default options 21 | # 22 | include mk/default.mk 23 | 24 | # 25 | # TOOLS ----------------------------------------------------------- 26 | # 27 | include mk/gcc.mk 28 | include mk/macros.mk 29 | 30 | # 31 | # Core/Device options --------------------------------------------- 32 | # 33 | CORE := 34 | 35 | STM32 := STM32F4xx 36 | DEVICE := STM32F412Zx 37 | DEVICE_CORE := cortex-m4 38 | 39 | include mk/$(DEVICE_CORE).mk 40 | 41 | CFLAGS-${CORE} += -D${DEVICE} 42 | 43 | LDSCRIPTS ?= $(BOARDS_DIR)/$(BOARD)/STM32F412ZGTX_FLASH.ld 44 | 45 | LDFLAGS += $(LDFLAGS-$(CORE)) 46 | LDFLAGS += -T$(LDSCRIPTS) 47 | 48 | include mk/common.mk 49 | -------------------------------------------------------------------------------- /Boards/nucleo-f412zg/Inc/bsp_ai.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file bsp_ai.h 15 | * \brief Link to board resources 16 | */ 17 | 18 | #ifndef BSP_H 19 | #define BSP_H 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include "main.h" 25 | #include "stm32f4xx.h" 26 | #include "app_x-cube-ai.h" 27 | #define UartHandle huart3 28 | #define MX_UARTx_Init MX_USART3_UART_Init 29 | void MX_USART3_UART_Init(void); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif /* BSP_H */ 36 | -------------------------------------------------------------------------------- /Boards/nucleo-f412zg/Inc/main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /* USER CODE BEGIN Header */ 14 | /** 15 | ****************************************************************************** 16 | * @file : main.h 17 | * @brief : Header for main.c file. 18 | * This file contains the common defines of the application. 19 | ****************************************************************************** 20 | */ 21 | /* USER CODE END Header */ 22 | 23 | /* Define to prevent recursive inclusion -------------------------------------*/ 24 | #ifndef __MAIN_H 25 | #define __MAIN_H 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | /* Includes ------------------------------------------------------------------*/ 32 | #include "stm32f4xx_hal.h" 33 | 34 | /* Private includes ----------------------------------------------------------*/ 35 | /* USER CODE BEGIN Includes */ 36 | 37 | /* USER CODE END Includes */ 38 | 39 | /* Exported types ------------------------------------------------------------*/ 40 | /* USER CODE BEGIN ET */ 41 | 42 | /* USER CODE END ET */ 43 | 44 | /* Exported constants --------------------------------------------------------*/ 45 | /* USER CODE BEGIN EC */ 46 | 47 | /* USER CODE END EC */ 48 | 49 | /* Exported macro ------------------------------------------------------------*/ 50 | /* USER CODE BEGIN EM */ 51 | 52 | /* USER CODE END EM */ 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 USER_Btn_Pin GPIO_PIN_13 63 | #define USER_Btn_GPIO_Port GPIOC 64 | #define MCO_Pin GPIO_PIN_0 65 | #define MCO_GPIO_Port GPIOH 66 | #define LD1_Pin GPIO_PIN_0 67 | #define LD1_GPIO_Port GPIOB 68 | #define LD3_Pin GPIO_PIN_14 69 | #define LD3_GPIO_Port GPIOB 70 | #define STLK_RX_Pin GPIO_PIN_8 71 | #define STLK_RX_GPIO_Port GPIOD 72 | #define STLK_TX_Pin GPIO_PIN_9 73 | #define STLK_TX_GPIO_Port GPIOD 74 | #define USB_PowerSwitchOn_Pin GPIO_PIN_6 75 | #define USB_PowerSwitchOn_GPIO_Port GPIOG 76 | #define USB_OverCurrent_Pin GPIO_PIN_7 77 | #define USB_OverCurrent_GPIO_Port GPIOG 78 | #define USB_SOF_Pin GPIO_PIN_8 79 | #define USB_SOF_GPIO_Port GPIOA 80 | #define USB_VBUS_Pin GPIO_PIN_9 81 | #define USB_VBUS_GPIO_Port GPIOA 82 | #define USB_ID_Pin GPIO_PIN_10 83 | #define USB_ID_GPIO_Port GPIOA 84 | #define USB_DM_Pin GPIO_PIN_11 85 | #define USB_DM_GPIO_Port GPIOA 86 | #define USB_DP_Pin GPIO_PIN_12 87 | #define USB_DP_GPIO_Port GPIOA 88 | #define TMS_Pin GPIO_PIN_13 89 | #define TMS_GPIO_Port GPIOA 90 | #define TCK_Pin GPIO_PIN_14 91 | #define TCK_GPIO_Port GPIOA 92 | #define SWO_Pin GPIO_PIN_3 93 | #define SWO_GPIO_Port GPIOB 94 | #define LD2_Pin GPIO_PIN_7 95 | #define LD2_GPIO_Port GPIOB 96 | /* USER CODE BEGIN Private defines */ 97 | 98 | /* USER CODE END Private defines */ 99 | 100 | #ifdef __cplusplus 101 | } 102 | #endif 103 | 104 | #endif /* __MAIN_H */ 105 | -------------------------------------------------------------------------------- /Boards/nucleo-f412zg/Inc/stm32f4xx_it.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /* USER CODE BEGIN Header */ 14 | /** 15 | ****************************************************************************** 16 | * @file stm32f4xx_it.h 17 | * @brief This file contains the headers of the interrupt handlers. 18 | ****************************************************************************** 19 | */ 20 | /* USER CODE END Header */ 21 | 22 | /* Define to prevent recursive inclusion -------------------------------------*/ 23 | #ifndef __STM32F4xx_IT_H 24 | #define __STM32F4xx_IT_H 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | /* Private includes ----------------------------------------------------------*/ 31 | /* USER CODE BEGIN Includes */ 32 | 33 | /* USER CODE END Includes */ 34 | 35 | /* Exported types ------------------------------------------------------------*/ 36 | /* USER CODE BEGIN ET */ 37 | 38 | /* USER CODE END ET */ 39 | 40 | /* Exported constants --------------------------------------------------------*/ 41 | /* USER CODE BEGIN EC */ 42 | 43 | /* USER CODE END EC */ 44 | 45 | /* Exported macro ------------------------------------------------------------*/ 46 | /* USER CODE BEGIN EM */ 47 | 48 | /* USER CODE END EM */ 49 | 50 | /* Exported functions prototypes ---------------------------------------------*/ 51 | void NMI_Handler(void); 52 | void HardFault_Handler(void); 53 | void MemManage_Handler(void); 54 | void BusFault_Handler(void); 55 | void UsageFault_Handler(void); 56 | void SVC_Handler(void); 57 | void DebugMon_Handler(void); 58 | void PendSV_Handler(void); 59 | void SysTick_Handler(void); 60 | /* USER CODE BEGIN EFP */ 61 | 62 | /* USER CODE END EFP */ 63 | 64 | #ifdef __cplusplus 65 | } 66 | #endif 67 | 68 | #endif /* __STM32F4xx_IT_H */ 69 | -------------------------------------------------------------------------------- /Boards/nucleo-f412zg/STM32F411RETX_FLASH.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /* 14 | ****************************************************************************** 15 | ** 16 | ** File : LinkerScript.ld 17 | ** 18 | ** Author : Auto-generated by STM32CubeIDE 19 | ** 20 | ** Abstract : Linker script for NUCLEO-F411RE Board embedding STM32F411RETx Device from STM32F4 series 21 | ** 512Kbytes FLASH 22 | ** 128Kbytes RAM 23 | ** 24 | ** Set heap size, stack size and stack location according 25 | ** to application requirements. 26 | ** 27 | ** Set memory bank area and size if external memory is used. 28 | ** 29 | ** Target : STMicroelectronics STM32 30 | ** 31 | ** Distribution: The file is distributed as is without any warranty 32 | ** of any kind. 33 | ** 34 | ***************************************************************************** 35 | */ 36 | 37 | /* Entry Point */ 38 | ENTRY(Reset_Handler) 39 | 40 | /* Highest address of the user mode stack */ 41 | _estack = 0x20020000; /* end of "RAM" Ram type memory */ 42 | 43 | _Min_Heap_Size = 0x2000 ; /* required amount of heap */ 44 | _Min_Stack_Size = 0x1000 ; /* required amount of stack */ 45 | 46 | /* Memories definition */ 47 | MEMORY 48 | { 49 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K 50 | FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K 51 | } 52 | 53 | /* Sections */ 54 | SECTIONS 55 | { 56 | /* The startup code into "FLASH" Rom type memory */ 57 | .isr_vector : 58 | { 59 | . = ALIGN(4); 60 | KEEP(*(.isr_vector)) /* Startup code */ 61 | . = ALIGN(4); 62 | } >FLASH 63 | 64 | /* The program code and other data into "FLASH" Rom type memory */ 65 | .text : 66 | { 67 | . = ALIGN(4); 68 | *(.text) /* .text sections (code) */ 69 | *(.text*) /* .text* sections (code) */ 70 | *(.glue_7) /* glue arm to thumb code */ 71 | *(.glue_7t) /* glue thumb to arm code */ 72 | *(.eh_frame) 73 | 74 | KEEP (*(.init)) 75 | KEEP (*(.fini)) 76 | 77 | . = ALIGN(4); 78 | _etext = .; /* define a global symbols at end of code */ 79 | } >FLASH 80 | 81 | /* Constant data into "FLASH" Rom type memory */ 82 | .rodata : 83 | { 84 | . = ALIGN(4); 85 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 86 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 87 | . = ALIGN(4); 88 | } >FLASH 89 | 90 | .ARM.extab : { 91 | . = ALIGN(4); 92 | *(.ARM.extab* .gnu.linkonce.armextab.*) 93 | . = ALIGN(4); 94 | } >FLASH 95 | 96 | .ARM : { 97 | . = ALIGN(4); 98 | __exidx_start = .; 99 | *(.ARM.exidx*) 100 | __exidx_end = .; 101 | . = ALIGN(4); 102 | } >FLASH 103 | 104 | .preinit_array : 105 | { 106 | . = ALIGN(4); 107 | PROVIDE_HIDDEN (__preinit_array_start = .); 108 | KEEP (*(.preinit_array*)) 109 | PROVIDE_HIDDEN (__preinit_array_end = .); 110 | . = ALIGN(4); 111 | } >FLASH 112 | 113 | .init_array : 114 | { 115 | . = ALIGN(4); 116 | PROVIDE_HIDDEN (__init_array_start = .); 117 | KEEP (*(SORT(.init_array.*))) 118 | KEEP (*(.init_array*)) 119 | PROVIDE_HIDDEN (__init_array_end = .); 120 | . = ALIGN(4); 121 | } >FLASH 122 | 123 | .fini_array : 124 | { 125 | . = ALIGN(4); 126 | PROVIDE_HIDDEN (__fini_array_start = .); 127 | KEEP (*(SORT(.fini_array.*))) 128 | KEEP (*(.fini_array*)) 129 | PROVIDE_HIDDEN (__fini_array_end = .); 130 | . = ALIGN(4); 131 | } >FLASH 132 | 133 | /* Used by the startup to initialize data */ 134 | _sidata = LOADADDR(.data); 135 | 136 | /* Initialized data sections into "RAM" Ram type memory */ 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 | 147 | } >RAM AT> FLASH 148 | 149 | /* Uninitialized data section into "RAM" Ram type memory */ 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" Ram type memory 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 | /* Remove information from the compiler libraries */ 177 | /DISCARD/ : 178 | { 179 | libc.a ( * ) 180 | libm.a ( * ) 181 | libgcc.a ( * ) 182 | } 183 | 184 | .ARM.attributes 0 : { *(.ARM.attributes) } 185 | } 186 | -------------------------------------------------------------------------------- /Boards/nucleo-f412zg/STM32F411RETX_RAM.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /* 14 | ****************************************************************************** 15 | ** 16 | ** File : LinkerScript.ld (debug in RAM dedicated) 17 | ** 18 | ** Author : Auto-generated by STM32CubeIDE 19 | ** 20 | ** Abstract : Linker script for NUCLEO-F411RE Board embedding STM32F411RETx Device from STM32F4 series 21 | ** 512Kbytes FLASH 22 | ** 128Kbytes RAM 23 | ** 24 | ** Set heap size, stack size and stack location according 25 | ** to application requirements. 26 | ** 27 | ** Set memory bank area and size if external memory is used. 28 | ** 29 | ** Target : STMicroelectronics STM32 30 | ** 31 | ** Distribution: The file is distributed as is without any warranty 32 | ** of any kind. 33 | ** 34 | ***************************************************************************** 35 | */ 36 | 37 | /* Entry Point */ 38 | ENTRY(Reset_Handler) 39 | 40 | /* Highest address of the user mode stack */ 41 | _estack = 0x20020000; /* end of "RAM" Ram type memory */ 42 | 43 | _Min_Heap_Size = 0x200; /* required amount of heap */ 44 | _Min_Stack_Size = 0x400; /* required amount of stack */ 45 | 46 | /* Memories definition */ 47 | MEMORY 48 | { 49 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K 50 | FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K 51 | } 52 | 53 | /* Sections */ 54 | SECTIONS 55 | { 56 | /* The startup code into "RAM" Ram type memory */ 57 | .isr_vector : 58 | { 59 | . = ALIGN(4); 60 | KEEP(*(.isr_vector)) /* Startup code */ 61 | . = ALIGN(4); 62 | } >RAM 63 | 64 | /* The program code and other data into "RAM" Ram type memory */ 65 | .text : 66 | { 67 | . = ALIGN(4); 68 | *(.text) /* .text sections (code) */ 69 | *(.text*) /* .text* sections (code) */ 70 | *(.glue_7) /* glue arm to thumb code */ 71 | *(.glue_7t) /* glue thumb to arm code */ 72 | *(.eh_frame) 73 | 74 | KEEP (*(.init)) 75 | KEEP (*(.fini)) 76 | 77 | . = ALIGN(4); 78 | _etext = .; /* define a global symbols at end of code */ 79 | } >RAM 80 | 81 | /* Constant data into "RAM" Ram type memory */ 82 | .rodata : 83 | { 84 | . = ALIGN(4); 85 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 86 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 87 | . = ALIGN(4); 88 | } >RAM 89 | 90 | .ARM.extab : { 91 | . = ALIGN(4); 92 | *(.ARM.extab* .gnu.linkonce.armextab.*) 93 | . = ALIGN(4); 94 | } >RAM 95 | 96 | .ARM : { 97 | . = ALIGN(4); 98 | __exidx_start = .; 99 | *(.ARM.exidx*) 100 | __exidx_end = .; 101 | . = ALIGN(4); 102 | } >RAM 103 | 104 | .preinit_array : 105 | { 106 | . = ALIGN(4); 107 | PROVIDE_HIDDEN (__preinit_array_start = .); 108 | KEEP (*(.preinit_array*)) 109 | PROVIDE_HIDDEN (__preinit_array_end = .); 110 | . = ALIGN(4); 111 | } >RAM 112 | 113 | .init_array : 114 | { 115 | . = ALIGN(4); 116 | PROVIDE_HIDDEN (__init_array_start = .); 117 | KEEP (*(SORT(.init_array.*))) 118 | KEEP (*(.init_array*)) 119 | PROVIDE_HIDDEN (__init_array_end = .); 120 | . = ALIGN(4); 121 | } >RAM 122 | 123 | .fini_array : 124 | { 125 | . = ALIGN(4); 126 | PROVIDE_HIDDEN (__fini_array_start = .); 127 | KEEP (*(SORT(.fini_array.*))) 128 | KEEP (*(.fini_array*)) 129 | PROVIDE_HIDDEN (__fini_array_end = .); 130 | . = ALIGN(4); 131 | } >RAM 132 | 133 | /* Used by the startup to initialize data */ 134 | _sidata = LOADADDR(.data); 135 | 136 | /* Initialized data sections into "RAM" Ram type memory */ 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 | 147 | } >RAM 148 | 149 | /* Uninitialized data section into "RAM" Ram type memory */ 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" Ram type memory 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 | /* Remove information from the compiler libraries */ 177 | /DISCARD/ : 178 | { 179 | libc.a ( * ) 180 | libm.a ( * ) 181 | libgcc.a ( * ) 182 | } 183 | 184 | .ARM.attributes 0 : { *(.ARM.attributes) } 185 | } 186 | -------------------------------------------------------------------------------- /Boards/nucleo-f412zg/STM32F412ZGTX_FLASH.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /* 14 | ****************************************************************************** 15 | ** 16 | ** File : LinkerScript.ld 17 | ** 18 | ** Author : Auto-generated by STM32CubeIDE 19 | ** 20 | ** Abstract : Linker script for NUCLEO-F411RE Board embedding STM32F411RETx Device from STM32F4 series 21 | ** 512Kbytes FLASH 22 | ** 128Kbytes RAM 23 | ** 24 | ** Set heap size, stack size and stack location according 25 | ** to application requirements. 26 | ** 27 | ** Set memory bank area and size if external memory is used. 28 | ** 29 | ** Target : STMicroelectronics STM32 30 | ** 31 | ** Distribution: The file is distributed as is without any warranty 32 | ** of any kind. 33 | ** 34 | ***************************************************************************** 35 | */ 36 | 37 | /* Entry Point */ 38 | ENTRY(Reset_Handler) 39 | 40 | _Min_Heap_Size = 0xE000 ; /* 56KB */ 41 | _Min_Stack_Size = 0x1000 ; /* 4KB */ 42 | 43 | /* Memories definition */ 44 | MEMORY 45 | { 46 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K 47 | FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K 48 | } 49 | 50 | /* Sections */ 51 | SECTIONS 52 | { 53 | /* The startup code into "FLASH" Rom type memory */ 54 | .isr_vector : 55 | { 56 | . = ALIGN(4); 57 | KEEP(*(.isr_vector)) /* Startup code */ 58 | . = ALIGN(4); 59 | } >FLASH 60 | 61 | /* The program code and other data into "FLASH" Rom type memory */ 62 | .text : 63 | { 64 | . = ALIGN(4); 65 | *(.text) /* .text sections (code) */ 66 | *(.text*) /* .text* sections (code) */ 67 | *(.glue_7) /* glue arm to thumb code */ 68 | *(.glue_7t) /* glue thumb to arm code */ 69 | *(.eh_frame) 70 | 71 | KEEP (*(.init)) 72 | KEEP (*(.fini)) 73 | 74 | . = ALIGN(4); 75 | _etext = .; /* define a global symbols at end of code */ 76 | } >FLASH 77 | 78 | /* Constant data into "FLASH" Rom type memory */ 79 | .rodata : 80 | { 81 | . = ALIGN(4); 82 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 83 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 84 | . = ALIGN(4); 85 | } >FLASH 86 | 87 | .ARM.extab : { 88 | . = ALIGN(4); 89 | *(.ARM.extab* .gnu.linkonce.armextab.*) 90 | . = ALIGN(4); 91 | } >FLASH 92 | 93 | .ARM : { 94 | . = ALIGN(4); 95 | __exidx_start = .; 96 | *(.ARM.exidx*) 97 | __exidx_end = .; 98 | . = ALIGN(4); 99 | } >FLASH 100 | 101 | .preinit_array : 102 | { 103 | . = ALIGN(4); 104 | PROVIDE_HIDDEN (__preinit_array_start = .); 105 | KEEP (*(.preinit_array*)) 106 | PROVIDE_HIDDEN (__preinit_array_end = .); 107 | . = ALIGN(4); 108 | } >FLASH 109 | 110 | .init_array : 111 | { 112 | . = ALIGN(4); 113 | PROVIDE_HIDDEN (__init_array_start = .); 114 | KEEP (*(SORT(.init_array.*))) 115 | KEEP (*(.init_array*)) 116 | PROVIDE_HIDDEN (__init_array_end = .); 117 | . = ALIGN(4); 118 | } >FLASH 119 | 120 | .fini_array : 121 | { 122 | . = ALIGN(4); 123 | PROVIDE_HIDDEN (__fini_array_start = .); 124 | KEEP (*(SORT(.fini_array.*))) 125 | KEEP (*(.fini_array*)) 126 | PROVIDE_HIDDEN (__fini_array_end = .); 127 | . = ALIGN(4); 128 | } >FLASH 129 | 130 | .nn_models : 131 | { 132 | . = ALIGN(4); 133 | __models_section_start__ = .; 134 | KEEP (*(.nn_models*)) 135 | __models_section_end__ = .; 136 | } >FLASH 137 | 138 | /* Used by the startup to initialize data */ 139 | _sidata = LOADADDR(.data); 140 | 141 | /* Initialized data sections into "RAM" Ram type memory */ 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 | 152 | } >RAM AT> FLASH 153 | 154 | ._params : 155 | { 156 | . = ALIGN(8); 157 | *(.nn_weights*) 158 | __external_params_pool__ = .; 159 | } >FLASH 160 | 161 | /* Uninitialized data section into "RAM" Ram type memory */ 162 | . = ALIGN(4); 163 | .bss : 164 | { 165 | /* This is used by the startup in order to initialize the .bss secion */ 166 | _sbss = .; /* define a global symbol at bss start */ 167 | __bss_start__ = _sbss; 168 | *(.bss) 169 | *(.bss*) 170 | *(COMMON) 171 | 172 | . = ALIGN(4); 173 | _ebss = .; /* define a global symbol at bss end */ 174 | __bss_end__ = _ebss; 175 | } >RAM 176 | 177 | .nn_data (NOLOAD) : 178 | { 179 | . = ALIGN(8); 180 | *(*.nn_data_act) 181 | *(.nn_data) 182 | *(.nn_data*) 183 | } >RAM 184 | 185 | /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ 186 | ._user_heap_stack : 187 | { 188 | . = ALIGN(8); 189 | PROVIDE ( end = . ); 190 | PROVIDE ( _end = . ); 191 | . = . + _Min_Heap_Size; 192 | _sstack = .; 193 | . = . + _Min_Stack_Size; 194 | _estack = .; 195 | . = ALIGN(8); 196 | } >RAM 197 | 198 | /* Remove information from the compiler libraries */ 199 | /DISCARD/ : 200 | { 201 | libc.a ( * ) 202 | libm.a ( * ) 203 | libgcc.a ( * ) 204 | } 205 | 206 | .ARM.attributes 0 : { *(.ARM.attributes) } 207 | } 208 | -------------------------------------------------------------------------------- /Boards/nucleo-f412zg/Src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /* USER CODE BEGIN Header */ 14 | /** 15 | ****************************************************************************** 16 | * @file : main.c 17 | * @brief : Main program body 18 | ****************************************************************************** 19 | */ 20 | /* USER CODE END Header */ 21 | /* Includes ------------------------------------------------------------------*/ 22 | #include 23 | #include "main.h" 24 | #include "app_x-cube-ai.h" 25 | 26 | /* Private includes ----------------------------------------------------------*/ 27 | /* USER CODE BEGIN Includes */ 28 | 29 | /* USER CODE END Includes */ 30 | 31 | /* Private typedef -----------------------------------------------------------*/ 32 | /* USER CODE BEGIN PTD */ 33 | 34 | /* USER CODE END PTD */ 35 | 36 | /* Private define ------------------------------------------------------------*/ 37 | /* USER CODE BEGIN PD */ 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 | UART_HandleTypeDef huart3; 47 | 48 | /* USER CODE BEGIN PV */ 49 | 50 | /* USER CODE END PV */ 51 | 52 | /* Private function prototypes -----------------------------------------------*/ 53 | void SystemClock_Config(void); 54 | static void MX_GPIO_Init(void); 55 | void MX_USART3_UART_Init(void); 56 | /* USER CODE BEGIN PFP */ 57 | 58 | /* USER CODE END PFP */ 59 | 60 | /* Private user code ---------------------------------------------------------*/ 61 | /* USER CODE BEGIN 0 */ 62 | 63 | /* USER CODE END 0 */ 64 | 65 | /** 66 | * @brief The application entry point. 67 | * @retval int 68 | */ 69 | int main(void) 70 | { 71 | /* USER CODE BEGIN 1 */ 72 | 73 | /* USER CODE END 1 */ 74 | 75 | /* MCU Configuration--------------------------------------------------------*/ 76 | 77 | /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ 78 | HAL_Init(); 79 | 80 | /* USER CODE BEGIN Init */ 81 | 82 | /* USER CODE END Init */ 83 | 84 | /* Configure the system clock */ 85 | SystemClock_Config(); 86 | 87 | /* USER CODE BEGIN SysInit */ 88 | 89 | /* USER CODE END SysInit */ 90 | 91 | /* Initialize all configured peripherals */ 92 | MX_GPIO_Init(); 93 | MX_USART3_UART_Init(); 94 | 95 | /* USER CODE BEGIN 2 */ 96 | 97 | MX_X_CUBE_AI_Init(); 98 | 99 | /* Display board setting */ 100 | printf("\r\nBoard setting (STM32F412ZG)\r\n"); 101 | 102 | /* USER CODE END 2 */ 103 | 104 | /* Infinite loop */ 105 | /* USER CODE BEGIN WHILE */ 106 | while (1) 107 | { 108 | /* USER CODE END WHILE */ 109 | MX_X_CUBE_AI_Process(); 110 | /* USER CODE BEGIN 3 */ 111 | } 112 | /* USER CODE END 3 */ 113 | } 114 | 115 | /** 116 | * @brief System Clock Configuration 117 | * @retval None 118 | */ 119 | void SystemClock_Config(void) 120 | { 121 | RCC_OscInitTypeDef RCC_OscInitStruct = {0}; 122 | RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; 123 | 124 | /** Configure the main internal regulator output voltage 125 | */ 126 | __HAL_RCC_PWR_CLK_ENABLE(); 127 | __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); 128 | /** Initializes the RCC Oscillators according to the specified parameters 129 | * in the RCC_OscInitTypeDef structure. 130 | */ 131 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; 132 | RCC_OscInitStruct.HSIState = RCC_HSI_ON; 133 | RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; 134 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 135 | RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; 136 | RCC_OscInitStruct.PLL.PLLM = 8; 137 | RCC_OscInitStruct.PLL.PLLN = 100; 138 | RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 139 | RCC_OscInitStruct.PLL.PLLQ = 2; 140 | RCC_OscInitStruct.PLL.PLLR = 2; 141 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) 142 | { 143 | Error_Handler(); 144 | } 145 | /** Initializes the CPU, AHB and APB buses clocks 146 | */ 147 | RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK 148 | |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; 149 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 150 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 151 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; 152 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 153 | 154 | if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK) 155 | { 156 | Error_Handler(); 157 | } 158 | } 159 | 160 | /** 161 | * @brief USART3 Initialization Function 162 | * @param None 163 | * @retval None 164 | */ 165 | void MX_USART3_UART_Init(void) 166 | { 167 | 168 | /* USER CODE BEGIN USART3_Init 0 */ 169 | 170 | /* USER CODE END USART3_Init 0 */ 171 | 172 | /* USER CODE BEGIN USART3_Init 1 */ 173 | 174 | /* USER CODE END USART3_Init 1 */ 175 | huart3.Instance = USART3; 176 | huart3.Init.BaudRate = 115200; 177 | huart3.Init.WordLength = UART_WORDLENGTH_8B; 178 | huart3.Init.StopBits = UART_STOPBITS_1; 179 | huart3.Init.Parity = UART_PARITY_NONE; 180 | huart3.Init.Mode = UART_MODE_TX_RX; 181 | huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; 182 | huart3.Init.OverSampling = UART_OVERSAMPLING_16; 183 | if (HAL_UART_Init(&huart3) != HAL_OK) 184 | { 185 | Error_Handler(); 186 | } 187 | /* USER CODE BEGIN USART3_Init 2 */ 188 | 189 | /* USER CODE END USART3_Init 2 */ 190 | 191 | } 192 | 193 | /** 194 | * @brief GPIO Initialization Function 195 | * @param None 196 | * @retval None 197 | */ 198 | static void MX_GPIO_Init(void) 199 | { 200 | GPIO_InitTypeDef GPIO_InitStruct = {0}; 201 | 202 | /* GPIO Ports Clock Enable */ 203 | __HAL_RCC_GPIOC_CLK_ENABLE(); 204 | __HAL_RCC_GPIOH_CLK_ENABLE(); 205 | __HAL_RCC_GPIOB_CLK_ENABLE(); 206 | __HAL_RCC_GPIOD_CLK_ENABLE(); 207 | __HAL_RCC_GPIOG_CLK_ENABLE(); 208 | __HAL_RCC_GPIOA_CLK_ENABLE(); 209 | 210 | /*Configure GPIO pin Output Level */ 211 | HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD3_Pin|LD2_Pin, GPIO_PIN_RESET); 212 | 213 | /*Configure GPIO pin Output Level */ 214 | HAL_GPIO_WritePin(USB_PowerSwitchOn_GPIO_Port, USB_PowerSwitchOn_Pin, GPIO_PIN_RESET); 215 | 216 | /*Configure GPIO pin : USER_Btn_Pin */ 217 | GPIO_InitStruct.Pin = USER_Btn_Pin; 218 | GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; 219 | GPIO_InitStruct.Pull = GPIO_NOPULL; 220 | HAL_GPIO_Init(USER_Btn_GPIO_Port, &GPIO_InitStruct); 221 | 222 | /*Configure GPIO pins : LD1_Pin LD3_Pin LD2_Pin */ 223 | GPIO_InitStruct.Pin = LD1_Pin|LD3_Pin|LD2_Pin; 224 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 225 | GPIO_InitStruct.Pull = GPIO_NOPULL; 226 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 227 | HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 228 | 229 | /*Configure GPIO pin : USB_PowerSwitchOn_Pin */ 230 | GPIO_InitStruct.Pin = USB_PowerSwitchOn_Pin; 231 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 232 | GPIO_InitStruct.Pull = GPIO_NOPULL; 233 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 234 | HAL_GPIO_Init(USB_PowerSwitchOn_GPIO_Port, &GPIO_InitStruct); 235 | 236 | /*Configure GPIO pin : USB_OverCurrent_Pin */ 237 | GPIO_InitStruct.Pin = USB_OverCurrent_Pin; 238 | GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 239 | GPIO_InitStruct.Pull = GPIO_NOPULL; 240 | HAL_GPIO_Init(USB_OverCurrent_GPIO_Port, &GPIO_InitStruct); 241 | 242 | /*Configure GPIO pins : USB_SOF_Pin USB_ID_Pin USB_DM_Pin USB_DP_Pin */ 243 | GPIO_InitStruct.Pin = USB_SOF_Pin|USB_ID_Pin|USB_DM_Pin|USB_DP_Pin; 244 | GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 245 | GPIO_InitStruct.Pull = GPIO_NOPULL; 246 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 247 | GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; 248 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 249 | 250 | } 251 | 252 | /* USER CODE BEGIN 4 */ 253 | 254 | /* USER CODE END 4 */ 255 | 256 | /** 257 | * @brief This function is executed in case of error occurrence. 258 | * @retval None 259 | */ 260 | void Error_Handler(void) 261 | { 262 | /* USER CODE BEGIN Error_Handler_Debug */ 263 | /* User can add his own implementation to report the HAL error return state */ 264 | __disable_irq(); 265 | while (1) 266 | { 267 | } 268 | /* USER CODE END Error_Handler_Debug */ 269 | } 270 | 271 | #ifdef USE_FULL_ASSERT 272 | /** 273 | * @brief Reports the name of the source file and the source line number 274 | * where the assert_param error has occurred. 275 | * @param file: pointer to the source file name 276 | * @param line: assert_param error line source number 277 | * @retval None 278 | */ 279 | void assert_failed(uint8_t *file, uint32_t line) 280 | { 281 | /* USER CODE BEGIN 6 */ 282 | /* User can add his own implementation to report the file name and line number, 283 | ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ 284 | /* USER CODE END 6 */ 285 | } 286 | #endif /* USE_FULL_ASSERT */ 287 | -------------------------------------------------------------------------------- /Boards/nucleo-f412zg/Src/stm32f4xx_hal_msp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /* USER CODE BEGIN Header */ 14 | /** 15 | ****************************************************************************** 16 | * @file stm32f4xx_hal_msp.c 17 | * @brief This file provides code for the MSP Initialization 18 | * and de-Initialization codes. 19 | ****************************************************************************** 20 | */ 21 | /* USER CODE END Header */ 22 | 23 | /* Includes ------------------------------------------------------------------*/ 24 | #include "main.h" 25 | /* USER CODE BEGIN Includes */ 26 | 27 | /* USER CODE END Includes */ 28 | 29 | /* Private typedef -----------------------------------------------------------*/ 30 | /* USER CODE BEGIN TD */ 31 | 32 | /* USER CODE END TD */ 33 | 34 | /* Private define ------------------------------------------------------------*/ 35 | /* USER CODE BEGIN Define */ 36 | 37 | /* USER CODE END Define */ 38 | 39 | /* Private macro -------------------------------------------------------------*/ 40 | /* USER CODE BEGIN Macro */ 41 | 42 | /* USER CODE END Macro */ 43 | 44 | /* Private variables ---------------------------------------------------------*/ 45 | /* USER CODE BEGIN PV */ 46 | 47 | /* USER CODE END PV */ 48 | 49 | /* Private function prototypes -----------------------------------------------*/ 50 | /* USER CODE BEGIN PFP */ 51 | 52 | /* USER CODE END PFP */ 53 | 54 | /* External functions --------------------------------------------------------*/ 55 | /* USER CODE BEGIN ExternalFunctions */ 56 | 57 | /* USER CODE END ExternalFunctions */ 58 | 59 | /* USER CODE BEGIN 0 */ 60 | 61 | /* USER CODE END 0 */ 62 | /** 63 | * Initializes the Global MSP. 64 | */ 65 | void HAL_MspInit(void) 66 | { 67 | /* USER CODE BEGIN MspInit 0 */ 68 | 69 | /* USER CODE END MspInit 0 */ 70 | 71 | __HAL_RCC_SYSCFG_CLK_ENABLE(); 72 | __HAL_RCC_PWR_CLK_ENABLE(); 73 | 74 | /* System interrupt init*/ 75 | 76 | /* USER CODE BEGIN MspInit 1 */ 77 | 78 | /* USER CODE END MspInit 1 */ 79 | } 80 | 81 | /** 82 | * @brief UART MSP Initialization 83 | * This function configures the hardware resources used in this example 84 | * @param huart: UART handle pointer 85 | * @retval None 86 | */ 87 | void HAL_UART_MspInit(UART_HandleTypeDef* huart) 88 | { 89 | GPIO_InitTypeDef GPIO_InitStruct = {0}; 90 | if(huart->Instance==USART3) 91 | { 92 | /* USER CODE BEGIN USART3_MspInit 0 */ 93 | 94 | /* USER CODE END USART3_MspInit 0 */ 95 | /* Peripheral clock enable */ 96 | __HAL_RCC_USART3_CLK_ENABLE(); 97 | 98 | __HAL_RCC_GPIOD_CLK_ENABLE(); 99 | /**USART3 GPIO Configuration 100 | PD8 ------> USART3_TX 101 | PD9 ------> USART3_RX 102 | */ 103 | GPIO_InitStruct.Pin = STLK_RX_Pin|STLK_TX_Pin; 104 | GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 105 | GPIO_InitStruct.Pull = GPIO_NOPULL; 106 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 107 | GPIO_InitStruct.Alternate = GPIO_AF7_USART3; 108 | HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); 109 | 110 | /* USER CODE BEGIN USART3_MspInit 1 */ 111 | 112 | /* USER CODE END USART3_MspInit 1 */ 113 | } 114 | 115 | } 116 | 117 | /** 118 | * @brief UART MSP De-Initialization 119 | * This function freeze the hardware resources used in this example 120 | * @param huart: UART handle pointer 121 | * @retval None 122 | */ 123 | void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) 124 | { 125 | if(huart->Instance==USART3) 126 | { 127 | /* USER CODE BEGIN USART3_MspDeInit 0 */ 128 | 129 | /* USER CODE END USART3_MspDeInit 0 */ 130 | /* Peripheral clock disable */ 131 | __HAL_RCC_USART3_CLK_DISABLE(); 132 | 133 | /**USART3 GPIO Configuration 134 | PD8 ------> USART3_TX 135 | PD9 ------> USART3_RX 136 | */ 137 | HAL_GPIO_DeInit(GPIOD, STLK_RX_Pin|STLK_TX_Pin); 138 | 139 | /* USER CODE BEGIN USART3_MspDeInit 1 */ 140 | 141 | /* USER CODE END USART3_MspDeInit 1 */ 142 | } 143 | 144 | } 145 | 146 | /* USER CODE BEGIN 1 */ 147 | 148 | /* USER CODE END 1 */ 149 | -------------------------------------------------------------------------------- /Boards/nucleo-f412zg/Src/stm32f4xx_it.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /* USER CODE BEGIN Header */ 14 | /** 15 | ****************************************************************************** 16 | * @file stm32f4xx_it.c 17 | * @brief Interrupt Service Routines. 18 | ****************************************************************************** 19 | */ 20 | /* USER CODE END Header */ 21 | 22 | /* Includes ------------------------------------------------------------------*/ 23 | #include "main.h" 24 | #include "stm32f4xx_it.h" 25 | /* Private includes ----------------------------------------------------------*/ 26 | /* USER CODE BEGIN Includes */ 27 | /* USER CODE END Includes */ 28 | 29 | /* Private typedef -----------------------------------------------------------*/ 30 | /* USER CODE BEGIN TD */ 31 | 32 | /* USER CODE END TD */ 33 | 34 | /* Private define ------------------------------------------------------------*/ 35 | /* USER CODE BEGIN PD */ 36 | 37 | /* USER CODE END PD */ 38 | 39 | /* Private macro -------------------------------------------------------------*/ 40 | /* USER CODE BEGIN PM */ 41 | 42 | /* USER CODE END PM */ 43 | 44 | /* Private variables ---------------------------------------------------------*/ 45 | /* USER CODE BEGIN PV */ 46 | 47 | /* USER CODE END PV */ 48 | 49 | /* Private function prototypes -----------------------------------------------*/ 50 | /* USER CODE BEGIN PFP */ 51 | 52 | /* USER CODE END PFP */ 53 | 54 | /* Private user code ---------------------------------------------------------*/ 55 | /* USER CODE BEGIN 0 */ 56 | 57 | /* USER CODE END 0 */ 58 | 59 | /* External variables --------------------------------------------------------*/ 60 | 61 | /* USER CODE BEGIN EV */ 62 | 63 | /* USER CODE END EV */ 64 | 65 | /******************************************************************************/ 66 | /* Cortex-M4 Processor Interruption and Exception Handlers */ 67 | /******************************************************************************/ 68 | /** 69 | * @brief This function handles Non maskable interrupt. 70 | */ 71 | void NMI_Handler(void) 72 | { 73 | /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ 74 | 75 | /* USER CODE END NonMaskableInt_IRQn 0 */ 76 | /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ 77 | while (1) 78 | { 79 | } 80 | /* USER CODE END NonMaskableInt_IRQn 1 */ 81 | } 82 | 83 | /** 84 | * @brief This function handles Hard fault interrupt. 85 | */ 86 | void HardFault_Handler(void) 87 | { 88 | /* USER CODE BEGIN HardFault_IRQn 0 */ 89 | 90 | /* USER CODE END HardFault_IRQn 0 */ 91 | while (1) 92 | { 93 | /* USER CODE BEGIN W1_HardFault_IRQn 0 */ 94 | /* USER CODE END W1_HardFault_IRQn 0 */ 95 | } 96 | } 97 | 98 | /** 99 | * @brief This function handles Memory management fault. 100 | */ 101 | void MemManage_Handler(void) 102 | { 103 | /* USER CODE BEGIN MemoryManagement_IRQn 0 */ 104 | 105 | /* USER CODE END MemoryManagement_IRQn 0 */ 106 | while (1) 107 | { 108 | /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ 109 | /* USER CODE END W1_MemoryManagement_IRQn 0 */ 110 | } 111 | } 112 | 113 | /** 114 | * @brief This function handles Pre-fetch fault, memory access fault. 115 | */ 116 | void BusFault_Handler(void) 117 | { 118 | /* USER CODE BEGIN BusFault_IRQn 0 */ 119 | 120 | /* USER CODE END BusFault_IRQn 0 */ 121 | while (1) 122 | { 123 | /* USER CODE BEGIN W1_BusFault_IRQn 0 */ 124 | /* USER CODE END W1_BusFault_IRQn 0 */ 125 | } 126 | } 127 | 128 | /** 129 | * @brief This function handles Undefined instruction or illegal state. 130 | */ 131 | void UsageFault_Handler(void) 132 | { 133 | /* USER CODE BEGIN UsageFault_IRQn 0 */ 134 | 135 | /* USER CODE END UsageFault_IRQn 0 */ 136 | while (1) 137 | { 138 | /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ 139 | /* USER CODE END W1_UsageFault_IRQn 0 */ 140 | } 141 | } 142 | 143 | /** 144 | * @brief This function handles System service call via SWI instruction. 145 | */ 146 | void SVC_Handler(void) 147 | { 148 | /* USER CODE BEGIN SVCall_IRQn 0 */ 149 | 150 | /* USER CODE END SVCall_IRQn 0 */ 151 | /* USER CODE BEGIN SVCall_IRQn 1 */ 152 | 153 | /* USER CODE END SVCall_IRQn 1 */ 154 | } 155 | 156 | /** 157 | * @brief This function handles Debug monitor. 158 | */ 159 | void DebugMon_Handler(void) 160 | { 161 | /* USER CODE BEGIN DebugMonitor_IRQn 0 */ 162 | 163 | /* USER CODE END DebugMonitor_IRQn 0 */ 164 | /* USER CODE BEGIN DebugMonitor_IRQn 1 */ 165 | 166 | /* USER CODE END DebugMonitor_IRQn 1 */ 167 | } 168 | 169 | /** 170 | * @brief This function handles Pendable request for system service. 171 | */ 172 | void PendSV_Handler(void) 173 | { 174 | /* USER CODE BEGIN PendSV_IRQn 0 */ 175 | 176 | /* USER CODE END PendSV_IRQn 0 */ 177 | /* USER CODE BEGIN PendSV_IRQn 1 */ 178 | 179 | /* USER CODE END PendSV_IRQn 1 */ 180 | } 181 | 182 | /** 183 | * @brief This function handles System tick timer. 184 | */ 185 | void SysTick_Handler(void) 186 | { 187 | /* USER CODE BEGIN SysTick_IRQn 0 */ 188 | 189 | /* USER CODE END SysTick_IRQn 0 */ 190 | HAL_IncTick(); 191 | /* USER CODE BEGIN SysTick_IRQn 1 */ 192 | 193 | /* USER CODE END SysTick_IRQn 1 */ 194 | } 195 | 196 | /******************************************************************************/ 197 | /* STM32F4xx Peripheral Interrupt Handlers */ 198 | /* Add here the Interrupt Handlers for the used peripherals. */ 199 | /* For the available peripheral interrupt handler names, */ 200 | /* please refer to the startup file (startup_stm32f4xx.s). */ 201 | /******************************************************************************/ 202 | 203 | /* USER CODE BEGIN 1 */ 204 | 205 | /* USER CODE END 1 */ 206 | -------------------------------------------------------------------------------- /Boards/nucleo-f412zg/files.mk: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | # Source files specific for this target 13 | 14 | # APP files 15 | C_SRC_APP += ${BOARDS_DIR}/${BOARD}/Src/main.c 16 | C_SRC_APP += ${BOARDS_DIR}/${BOARD}/Src/stm32f4xx_hal_msp.c 17 | C_SRC_APP += ${BOARDS_DIR}/${BOARD}/Src/stm32f4xx_it.c 18 | C_SRC_APP += ${BOARDS_DIR}/${BOARD}/Src/system_stm32f4xx.c 19 | 20 | CFLAGS += -DUSE_HAL_DRIVER 21 | 22 | # Startup file 23 | ASM_SRC_APP += ${BOARDS_DIR}/${BOARD}/Asm/startup_stm32f412zgtx.s 24 | 25 | # HAL files 26 | 27 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal.c 28 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_cortex.c 29 | #C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_crc.c 30 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_dma.c 31 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_dma_ex.c 32 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_exti.c 33 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_flash.c 34 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_flash_ex.c 35 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_flash_ramfunc.c 36 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_gpio.c 37 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_pwr.c 38 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_pwr_ex.c 39 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_rcc.c 40 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_rcc_ex.c 41 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_tim.c 42 | # C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_tim_ex.c 43 | C_SRC_HAL += ${HAL_DIR_ROOT}/Src/stm32f4xx_hal_uart.c 44 | 45 | CFLAGS += -I${HAL_DIR_ROOT}/Inc 46 | 47 | C_SOURCES += ${C_SRC_APP} ${C_SRC_HAL} 48 | ASM_SOURCES += ${ASM_SRC_APP} 49 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | 2 | ## Contributing guide 3 | 4 | The issues and the pull-requests are not supported for submitting problems or suggestions related to the software delivered in this repository. The TVM STM32 demo applications are being delivered as-is, not necessarily supported by ST. 5 | 6 | For any question related to the product, the hardware performance or characteristics, the tools, the environment, you can submit it to the ST Community on the STM32 MCUs related page. 7 | -------------------------------------------------------------------------------- /Inc/Misc/aiTestTvmHelper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file aiTestTvmHelper.h 15 | * \brief STM32 Helper functions for STM32 AI test application 16 | */ 17 | 18 | #ifndef __AI_TEST_TVM_HELPER_H__ 19 | #define __AI_TEST_TVM_HELPER_H__ 20 | 21 | #include 22 | 23 | #include "ai_runtime_api.h" 24 | #include "ai_platform.h" 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | void aiPlatformVersion(void); 31 | 32 | void aiLogErr(const char *fct, const char *err); 33 | void aiPrintLayoutBuffer(const char *msg, int idx, ai_tensor * tensor); 34 | void aiPrintNetworkInfo(ai_model_info *nn, ai_handle hdl); 35 | 36 | #if defined(NO_X_CUBE_AI_RUNTIME) && NO_X_CUBE_AI_RUNTIME == 1 37 | #include "ai_platform.h" 38 | void aiTvmToReport(ai_model_info *nn, ai_handle hdl, ai_network_report *report); 39 | #endif 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | #endif /* __AI_TEST_TVM_HELPER_H__ */ 46 | -------------------------------------------------------------------------------- /Inc/SystemPerformance/aiSystemPerformance.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file aiSystemPerformance.h 15 | * \brief Entry points for AI system performance application 16 | */ 17 | 18 | #ifndef __AI_SYSTEM_PERFORMANCE_H__ 19 | #define __AI_SYSTEM_PERFORMANCE_H__ 20 | 21 | #include 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | int aiSystemPerformanceInit(void); 28 | int aiSystemPerformanceProcess(void); 29 | void aiSystemPerformanceDeInit(void); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif /* __AI_SYSTEM_PERFORMANCE_H__ */ 36 | -------------------------------------------------------------------------------- /Inc/Validation/aiPbIO.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file aiPbIO.h 15 | * \brief Low Level nano PB stack functions 16 | */ 17 | 18 | #ifndef _AI_PB_IO_H_ 19 | #define _AI_PB_IO_H_ 20 | 21 | #include 22 | 23 | int pb_io_stream_init(void); 24 | 25 | void pb_io_flush_ostream(void); 26 | void pb_io_flush_istream(void); 27 | 28 | pb_ostream_t pb_io_ostream(int fd); 29 | pb_istream_t pb_io_istream(int fd); 30 | 31 | #endif /* _AI_PB_IO_H_ */ 32 | 33 | -------------------------------------------------------------------------------- /Inc/Validation/aiPbMgr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file aiPbMgr.h 15 | * \brief Helper function for AI ProtoBuffer support 16 | */ 17 | 18 | #ifndef _AI_PB_MGR_H_ 19 | #define _AI_PB_MGR_H_ 20 | 21 | #include "ai_platform.h" 22 | 23 | #include "pb.h" 24 | #include "stm32msg.pb.h" 25 | 26 | #ifndef AI_PB_TEST 27 | #define AI_PB_TEST 0 28 | #endif 29 | 30 | /* AI_PB_FULL_IO - force the upload of the ai_buffer with AI_BUFFER_FMT_FLAG_IS_IO flag 31 | * (see aiPbMgrSendAiBuffer3() function) */ 32 | #ifndef AI_PB_FULL_IO 33 | #define AI_PB_FULL_IO 0 34 | #endif 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | 41 | /* --------------------------- */ 42 | 43 | #if TF_LITE_STATIC_MEMORY /* C-define used to build the TFLM 2.3 files */ 44 | #if !defined(NO_X_CUBE_AI_RUNTIME) 45 | #define NO_X_CUBE_AI_RUNTIME 1 46 | #endif 47 | #endif 48 | 49 | #if defined(NO_X_CUBE_AI_RUNTIME) && NO_X_CUBE_AI_RUNTIME == 1 50 | 51 | /* Special definition */ 52 | struct ai_buffer_extra { 53 | float scale; 54 | int zero_point; 55 | }; 56 | 57 | struct ai_buffer_ext { 58 | ai_buffer buffer; 59 | struct ai_buffer_extra extra; 60 | }; 61 | #endif 62 | 63 | /* --------------------------- */ 64 | 65 | typedef struct _aiPbCmdFunc { 66 | EnumCmd cmd; 67 | void (*process)(const reqMsg *req, respMsg *resp, void *param); 68 | void *param; 69 | } aiPbCmdFunc; 70 | 71 | void aiPbMgrInit(const aiPbCmdFunc *funcs); 72 | 73 | int aiPbMgrWaitAndProcess(void); 74 | 75 | /* --------------------------- */ 76 | 77 | void aiPbMgrSendAck(const reqMsg *req, respMsg *resp, 78 | EnumState state, uint32_t param, EnumError error); 79 | 80 | void aiPbMgrSendResp(const reqMsg *req, respMsg *resp, EnumState state); 81 | 82 | bool aiPbMgrReceiveAiBuffer3(const reqMsg *req, respMsg *resp, 83 | EnumState state, ai_buffer *buffer); 84 | 85 | #define PB_BUFFER_TYPE_SEND_WITHOUT_DATA ((uint32_t)(1U << 31)) 86 | 87 | bool aiPbMgrSendAiBuffer4(const reqMsg *req, respMsg *resp, EnumState state, 88 | uint32_t type, uint32_t id, ai_float dur_ms, const ai_buffer *buffer, 89 | ai_float scale, ai_i32 zero_point); 90 | 91 | bool aiPbMgrSendLog(const reqMsg *req, respMsg *resp, 92 | EnumState state, uint32_t lvl, const char *str); 93 | 94 | void aiPbMgrSendNNInfo(const reqMsg *req, respMsg *resp, 95 | EnumState state, const ai_network_report *nn); 96 | 97 | bool aiPbMgrWaitAck(void); 98 | 99 | /* --------------------------- */ 100 | 101 | uint32_t aiPbAiBufferSize(const ai_buffer *buffer); 102 | void aiPbStrCopy(const char *src, char *dst, uint32_t max); 103 | uint32_t aiPbVersionToUint32(const ai_platform_version *ver); 104 | 105 | /* --------------------------- */ 106 | 107 | void aiPbCmdSync(const reqMsg *req, respMsg *resp, void *param); 108 | #define AI_PB_CMD_SYNC(par) { EnumCmd_CMD_SYNC, &aiPbCmdSync, (par) } 109 | 110 | void aiPbCmdSysInfo(const reqMsg *req, respMsg *resp, void *param); 111 | #define AI_PB_CMD_SYS_INFO(par) { EnumCmd_CMD_SYS_INFO, &aiPbCmdSysInfo, (par) } 112 | 113 | #define AI_PB_CMD_END { (EnumCmd)0, NULL, NULL } 114 | 115 | #if defined(AI_PB_TEST) && (AI_PB_TEST == 1) 116 | void aiPbTestCmd(const reqMsg *req, respMsg *resp, void *param); 117 | #define AI_PB_CMD_TEST(par) { EnumCmd_CMD_TEST, &aiPbTestCmd, (par) } 118 | #endif 119 | 120 | 121 | #ifdef __cplusplus 122 | } /* extern "C" */ 123 | #endif 124 | 125 | #endif /* _AI_PB_MGR_H_ */ 126 | -------------------------------------------------------------------------------- /Inc/Validation/aiValidation.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file aiValidation.h 15 | * \brief AI Validation application 16 | */ 17 | 18 | #ifndef __AI_VALIDATION_H__ 19 | #define __AI_VALIDATION_H__ 20 | 21 | #include 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | int aiValidationInit(void); 28 | int aiValidationProcess(void); 29 | void aiValidationDeInit(void); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif /* __AI_VALIDATION_H__ */ 36 | -------------------------------------------------------------------------------- /Inc/Validation/pb_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Petteri Aimonen 3 | * 4 | * This software is provided 'as-is', without any express or 5 | * implied warranty. In no event will the authors be held liable 6 | * for any damages arising from the use of this software. 7 | * 8 | * Permission is granted to anyone to use this software for any 9 | * purpose, including commercial applications, and to alter it and 10 | * redistribute it freely, subject to the following restrictions: 11 | * 12 | * 1. The origin of this software must not be misrepresented; you 13 | * must not claim that you wrote the original software. If you use 14 | * this software in a product, an acknowledgment in the product 15 | * documentation would be appreciated but is not required. 16 | * 17 | * 2. Altered source versions must be plainly marked as such, and 18 | * must not be misrepresented as being the original software. 19 | * 20 | * 3. This notice may not be removed or altered from any source 21 | * distribution. 22 | */ 23 | 24 | /* 25 | * Included from: https://github.com/nanopb/nanopb/ 26 | */ 27 | 28 | /*! 29 | * \file pb_common.h 30 | * \brief Common support functions for pb_encode.c and 31 | * pb_decode.c. These functions are rarely needed by 32 | * applications directly. 33 | */ 34 | 35 | #ifndef PB_COMMON_H_INCLUDED 36 | #define PB_COMMON_H_INCLUDED 37 | 38 | #include "pb.h" 39 | 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | 44 | /* Iterator for pb_field_t list */ 45 | struct pb_field_iter_s { 46 | const pb_field_t *start; /* Start of the pb_field_t array */ 47 | const pb_field_t *pos; /* Current position of the iterator */ 48 | unsigned required_field_index; /* Zero-based index that counts only the required fields */ 49 | void *dest_struct; /* Pointer to start of the structure */ 50 | void *pData; /* Pointer to current field value */ 51 | void *pSize; /* Pointer to count/has field */ 52 | }; 53 | typedef struct pb_field_iter_s pb_field_iter_t; 54 | 55 | /* Initialize the field iterator structure to beginning. 56 | * Returns false if the message type is empty. */ 57 | bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct); 58 | 59 | /* Advance the iterator to the next field. 60 | * Returns false when the iterator wraps back to the first field. */ 61 | bool pb_field_iter_next(pb_field_iter_t *iter); 62 | 63 | /* Advance the iterator until it points at a field with the given tag. 64 | * Returns false if no such field exists. */ 65 | bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag); 66 | 67 | #ifdef __cplusplus 68 | } /* extern "C" */ 69 | #endif 70 | 71 | #endif 72 | 73 | -------------------------------------------------------------------------------- /Inc/Validation/pb_decode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Petteri Aimonen 3 | * 4 | * This software is provided 'as-is', without any express or 5 | * implied warranty. In no event will the authors be held liable 6 | * for any damages arising from the use of this software. 7 | * 8 | * Permission is granted to anyone to use this software for any 9 | * purpose, including commercial applications, and to alter it and 10 | * redistribute it freely, subject to the following restrictions: 11 | * 12 | * 1. The origin of this software must not be misrepresented; you 13 | * must not claim that you wrote the original software. If you use 14 | * this software in a product, an acknowledgment in the product 15 | * documentation would be appreciated but is not required. 16 | * 17 | * 2. Altered source versions must be plainly marked as such, and 18 | * must not be misrepresented as being the original software. 19 | * 20 | * 3. This notice may not be removed or altered from any source 21 | * distribution. 22 | */ 23 | 24 | /* 25 | * Included from: https://github.com/nanopb/nanopb/ 26 | */ 27 | 28 | /*! 29 | * \file decode.h 30 | * \brief Functions to decode protocol buffers. Depends on 31 | * pb_decode.c. The main function is pb_decode. You also 32 | * need an input stream, and the field descriptions 33 | * created by nanopb_generator.py. 34 | */ 35 | 36 | #ifndef PB_DECODE_H_INCLUDED 37 | #define PB_DECODE_H_INCLUDED 38 | 39 | #include "pb.h" 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | /* Structure for defining custom input streams. You will need to provide 46 | * a callback function to read the bytes from your storage, which can be 47 | * for example a file or a network socket. 48 | * 49 | * The callback must conform to these rules: 50 | * 51 | * 1) Return false on IO errors. This will cause decoding to abort. 52 | * 2) You can use state to store your own data (e.g. buffer pointer), 53 | * and rely on pb_read to verify that no-body reads past bytes_left. 54 | * 3) Your callback may be used with substreams, in which case bytes_left 55 | * is different than from the main stream. Don't use bytes_left to compute 56 | * any pointers. 57 | */ 58 | struct pb_istream_s 59 | { 60 | #ifdef PB_BUFFER_ONLY 61 | /* Callback pointer is not used in buffer-only configuration. 62 | * Having an int pointer here allows binary compatibility but 63 | * gives an error if someone tries to assign callback function. 64 | */ 65 | int *callback; 66 | #else 67 | bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count); 68 | #endif 69 | 70 | void *state; /* Free field for use by callback implementation */ 71 | size_t bytes_left; 72 | 73 | #ifndef PB_NO_ERRMSG 74 | const char *errmsg; 75 | #endif 76 | }; 77 | 78 | /*************************** 79 | * Main decoding functions * 80 | ***************************/ 81 | 82 | /* Decode a single protocol buffers message from input stream into a C structure. 83 | * Returns true on success, false on any failure. 84 | * The actual struct pointed to by dest must match the description in fields. 85 | * Callback fields of the destination structure must be initialized by caller. 86 | * All other fields will be initialized by this function. 87 | * 88 | * Example usage: 89 | * MyMessage msg = {}; 90 | * uint8_t buffer[64]; 91 | * pb_istream_t stream; 92 | * 93 | * // ... read some data into buffer ... 94 | * 95 | * stream = pb_istream_from_buffer(buffer, count); 96 | * pb_decode(&stream, MyMessage_fields, &msg); 97 | */ 98 | bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); 99 | 100 | /* Same as pb_decode, except does not initialize the destination structure 101 | * to default values. This is slightly faster if you need no default values 102 | * and just do memset(struct, 0, sizeof(struct)) yourself. 103 | * 104 | * This can also be used for 'merging' two messages, i.e. update only the 105 | * fields that exist in the new message. 106 | * 107 | * Note: If this function returns with an error, it will not release any 108 | * dynamically allocated fields. You will need to call pb_release() yourself. 109 | */ 110 | bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); 111 | 112 | /* Same as pb_decode, except expects the stream to start with the message size 113 | * encoded as varint. Corresponds to parseDelimitedFrom() in Google's 114 | * protobuf API. 115 | */ 116 | bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); 117 | 118 | /* Same as pb_decode_delimited, except that it does not initialize the destination structure. 119 | * See pb_decode_noinit 120 | */ 121 | bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); 122 | 123 | /* Same as pb_decode, except allows the message to be terminated with a null byte. 124 | * NOTE: Until nanopb-0.4.0, pb_decode() also allows null-termination. This behaviour 125 | * is not supported in most other protobuf implementations, so pb_decode_delimited() 126 | * is a better option for compatibility. 127 | */ 128 | bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); 129 | 130 | #ifdef PB_ENABLE_MALLOC 131 | /* Release any allocated pointer fields. If you use dynamic allocation, you should 132 | * call this for any successfully decoded message when you are done with it. If 133 | * pb_decode() returns with an error, the message is already released. 134 | */ 135 | void pb_release(const pb_field_t fields[], void *dest_struct); 136 | #endif 137 | 138 | 139 | /************************************** 140 | * Functions for manipulating streams * 141 | **************************************/ 142 | 143 | /* Create an input stream for reading from a memory buffer. 144 | * 145 | * Alternatively, you can use a custom stream that reads directly from e.g. 146 | * a file or a network socket. 147 | */ 148 | pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize); 149 | 150 | /* Function to read from a pb_istream_t. You can use this if you need to 151 | * read some custom header data, or to read data in field callbacks. 152 | */ 153 | bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); 154 | 155 | 156 | /************************************************ 157 | * Helper functions for writing field callbacks * 158 | ************************************************/ 159 | 160 | /* Decode the tag for the next field in the stream. Gives the wire type and 161 | * field tag. At end of the message, returns false and sets eof to true. */ 162 | bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof); 163 | 164 | /* Skip the field payload data, given the wire type. */ 165 | bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type); 166 | 167 | /* Decode an integer in the varint format. This works for bool, enum, int32, 168 | * int64, uint32 and uint64 field types. */ 169 | #ifndef PB_WITHOUT_64BIT 170 | bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest); 171 | #else 172 | #define pb_decode_varint pb_decode_varint32 173 | #endif 174 | 175 | /* Decode an integer in the varint format. This works for bool, enum, int32, 176 | * and uint32 field types. */ 177 | bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); 178 | 179 | /* Decode an integer in the zig-zagged svarint format. This works for sint32 180 | * and sint64. */ 181 | #ifndef PB_WITHOUT_64BIT 182 | bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest); 183 | #else 184 | bool pb_decode_svarint(pb_istream_t *stream, int32_t *dest); 185 | #endif 186 | 187 | /* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to 188 | * a 4-byte wide C variable. */ 189 | bool pb_decode_fixed32(pb_istream_t *stream, void *dest); 190 | 191 | #ifndef PB_WITHOUT_64BIT 192 | /* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to 193 | * a 8-byte wide C variable. */ 194 | bool pb_decode_fixed64(pb_istream_t *stream, void *dest); 195 | #endif 196 | 197 | /* Make a limited-length substream for reading a PB_WT_STRING field. */ 198 | bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream); 199 | bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream); 200 | 201 | #ifdef __cplusplus 202 | } /* extern "C" */ 203 | #endif 204 | 205 | #endif 206 | -------------------------------------------------------------------------------- /Inc/Validation/pb_encode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Petteri Aimonen 3 | * 4 | * This software is provided 'as-is', without any express or 5 | * implied warranty. In no event will the authors be held liable 6 | * for any damages arising from the use of this software. 7 | * 8 | * Permission is granted to anyone to use this software for any 9 | * purpose, including commercial applications, and to alter it and 10 | * redistribute it freely, subject to the following restrictions: 11 | * 12 | * 1. The origin of this software must not be misrepresented; you 13 | * must not claim that you wrote the original software. If you use 14 | * this software in a product, an acknowledgment in the product 15 | * documentation would be appreciated but is not required. 16 | * 17 | * 2. Altered source versions must be plainly marked as such, and 18 | * must not be misrepresented as being the original software. 19 | * 20 | * 3. This notice may not be removed or altered from any source 21 | * distribution. 22 | */ 23 | 24 | /* 25 | * Included from: https://github.com/nanopb/nanopb/ 26 | */ 27 | 28 | /*! 29 | * \file pb_encode.h 30 | * \brief Functions to encode protocol buffers. Depends on 31 | * pb_encode.c. The main function is pb_encode. You also 32 | * need an output stream, and the field descriptions 33 | * created by nanopb_generator.py. 34 | */ 35 | 36 | #ifndef PB_ENCODE_H_INCLUDED 37 | #define PB_ENCODE_H_INCLUDED 38 | 39 | #include "pb.h" 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | /* Structure for defining custom output streams. You will need to provide 46 | * a callback function to write the bytes to your storage, which can be 47 | * for example a file or a network socket. 48 | * 49 | * The callback must conform to these rules: 50 | * 51 | * 1) Return false on IO errors. This will cause encoding to abort. 52 | * 2) You can use state to store your own data (e.g. buffer pointer). 53 | * 3) pb_write will update bytes_written after your callback runs. 54 | * 4) Substreams will modify max_size and bytes_written. Don't use them 55 | * to calculate any pointers. 56 | */ 57 | struct pb_ostream_s 58 | { 59 | #ifdef PB_BUFFER_ONLY 60 | /* Callback pointer is not used in buffer-only configuration. 61 | * Having an int pointer here allows binary compatibility but 62 | * gives an error if someone tries to assign callback function. 63 | * Also, NULL pointer marks a 'sizing stream' that does not 64 | * write anything. 65 | */ 66 | int *callback; 67 | #else 68 | bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); 69 | #endif 70 | void *state; /* Free field for use by callback implementation. */ 71 | size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ 72 | size_t bytes_written; /* Number of bytes written so far. */ 73 | 74 | #ifndef PB_NO_ERRMSG 75 | const char *errmsg; 76 | #endif 77 | }; 78 | 79 | /*************************** 80 | * Main encoding functions * 81 | ***************************/ 82 | 83 | /* Encode a single protocol buffers message from C structure into a stream. 84 | * Returns true on success, false on any failure. 85 | * The actual struct pointed to by src_struct must match the description in fields. 86 | * All required fields in the struct are assumed to have been filled in. 87 | * 88 | * Example usage: 89 | * MyMessage msg = {}; 90 | * uint8_t buffer[64]; 91 | * pb_ostream_t stream; 92 | * 93 | * msg.field1 = 42; 94 | * stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); 95 | * pb_encode(&stream, MyMessage_fields, &msg); 96 | */ 97 | bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); 98 | 99 | /* Same as pb_encode, but prepends the length of the message as a varint. 100 | * Corresponds to writeDelimitedTo() in Google's protobuf API. 101 | */ 102 | bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); 103 | 104 | /* Same as pb_encode, but appends a null byte to the message for termination. 105 | * NOTE: This behaviour is not supported in most other protobuf implementations, so pb_encode_delimited() 106 | * is a better option for compatibility. 107 | */ 108 | bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); 109 | 110 | /* Encode the message to get the size of the encoded data, but do not store 111 | * the data. */ 112 | bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct); 113 | 114 | /************************************** 115 | * Functions for manipulating streams * 116 | **************************************/ 117 | 118 | /* Create an output stream for writing into a memory buffer. 119 | * The number of bytes written can be found in stream.bytes_written after 120 | * encoding the message. 121 | * 122 | * Alternatively, you can use a custom stream that writes directly to e.g. 123 | * a file or a network socket. 124 | */ 125 | pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize); 126 | 127 | /* Pseudo-stream for measuring the size of a message without actually storing 128 | * the encoded data. 129 | * 130 | * Example usage: 131 | * MyMessage msg = {}; 132 | * pb_ostream_t stream = PB_OSTREAM_SIZING; 133 | * pb_encode(&stream, MyMessage_fields, &msg); 134 | * printf("Message size is %d\n", stream.bytes_written); 135 | */ 136 | #ifndef PB_NO_ERRMSG 137 | #define PB_OSTREAM_SIZING {0,0,0,0,0} 138 | #else 139 | #define PB_OSTREAM_SIZING {0,0,0,0} 140 | #endif 141 | 142 | /* Function to write into a pb_ostream_t stream. You can use this if you need 143 | * to append or prepend some custom headers to the message. 144 | */ 145 | bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); 146 | 147 | 148 | /************************************************ 149 | * Helper functions for writing field callbacks * 150 | ************************************************/ 151 | 152 | /* Encode field header based on type and field number defined in the field 153 | * structure. Call this from the callback before writing out field contents. */ 154 | bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field); 155 | 156 | /* Encode field header by manually specifing wire type. You need to use this 157 | * if you want to write out packed arrays from a callback field. */ 158 | bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number); 159 | 160 | /* Encode an integer in the varint format. 161 | * This works for bool, enum, int32, int64, uint32 and uint64 field types. */ 162 | #ifndef PB_WITHOUT_64BIT 163 | bool pb_encode_varint(pb_ostream_t *stream, uint64_t value); 164 | #else 165 | bool pb_encode_varint(pb_ostream_t *stream, uint32_t value); 166 | #endif 167 | 168 | /* Encode an integer in the zig-zagged svarint format. 169 | * This works for sint32 and sint64. */ 170 | #ifndef PB_WITHOUT_64BIT 171 | bool pb_encode_svarint(pb_ostream_t *stream, int64_t value); 172 | #else 173 | bool pb_encode_svarint(pb_ostream_t *stream, int32_t value); 174 | #endif 175 | 176 | /* Encode a string or bytes type field. For strings, pass strlen(s) as size. */ 177 | bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size); 178 | 179 | /* Encode a fixed32, sfixed32 or float value. 180 | * You need to pass a pointer to a 4-byte wide C variable. */ 181 | bool pb_encode_fixed32(pb_ostream_t *stream, const void *value); 182 | 183 | #ifndef PB_WITHOUT_64BIT 184 | /* Encode a fixed64, sfixed64 or double value. 185 | * You need to pass a pointer to a 8-byte wide C variable. */ 186 | bool pb_encode_fixed64(pb_ostream_t *stream, const void *value); 187 | #endif 188 | 189 | /* Encode a submessage field. 190 | * You need to pass the pb_field_t array and pointer to struct, just like 191 | * with pb_encode(). This internally encodes the submessage twice, first to 192 | * calculate message size and then to actually write it out. 193 | */ 194 | bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); 195 | 196 | #ifdef __cplusplus 197 | } /* extern "C" */ 198 | #endif 199 | 200 | #endif 201 | -------------------------------------------------------------------------------- /Inc/app_x-cube-ai.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file app_x-cube-ai.h 15 | * \brief AI entry function definitions 16 | */ 17 | 18 | #ifndef __APP_AI_H 19 | #define __APP_AI_H 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | void MX_X_CUBE_AI_Init(void); 26 | void MX_X_CUBE_AI_Process(void); 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif /*__APP_AI_H */ 33 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | # Top level Makefile for the STM32 microcontroller project. 13 | 14 | # 15 | # Set the path to your ARM Toolset. 16 | # Only gcc is supported at this time. 17 | # 18 | #export ARM_PATH ?= 19 | ifndef ARM_PATH 20 | $(error ARM_PATH must be set and point at your GCC ARM compiler installation) 21 | endif 22 | 23 | # 24 | # Set the path to your TVM compiler installation 25 | # 26 | #export TVM_PATH ?= 27 | ifndef TVM_PATH 28 | $(error TVM_PATH must be set and point at your TVM stack installation) 29 | endif 30 | 31 | #export X_CUBE_TOOL_PATH ?= 32 | ifndef X_CUBE_TOOL_PATH 33 | $(error X_CUBE_TOOL_PATH must be set and point at your STM32 Cube Programmer installation) 34 | endif 35 | 36 | # 37 | # Choose a board from the list below and setup the firmware path 38 | # 39 | 40 | # ----------------------------------- 41 | # Disco 42 | # ----------------------------------- 43 | #BOARD = disco-h747i 44 | #SERIAL_NUMBER = 45 | #export X_CUBE_PATH = 46 | 47 | # ----------------------------------- 48 | # Nucleao 49 | # ----------------------------------- 50 | #BOARD = nucleo-f412zg 51 | #SERIAL_NUMBER = 52 | #export X_CUBE_PATH = 53 | 54 | # Indicate the revision of the board (if necessary) 55 | # xyy with x:1 for A, 2 for B ... 56 | # yy:01 ... 57 | # ex: MB1361-L552ZEQ-C02 -> 302 58 | # MB1361-L552ZEQ-A02 -> 102 59 | # BOARD_VERSION ?= 102 60 | 61 | ifeq ($(BOARD), disco-h747i) 62 | EXTLOAD = "${X_CUBE_TOOL_PATH}/ExternalLoader/MT25TL01G_STM32H747I-DISCO.stldr" 63 | endif 64 | 65 | # 115200 66 | # BAUDRATE = 921600 67 | 68 | STM32_PROG ?= ${X_CUBE_TOOL_PATH}/STM32_Programmer_CLI 69 | 70 | ifdef EXTLOAD 71 | STM32_PROG += --extload $(EXTLOAD) 72 | endif 73 | 74 | BUILD_DIR = ./build/$(BOARD) 75 | BOARDS_DIR = ./Boards 76 | 77 | APP_NAME = Project 78 | 79 | debug: 80 | @echo " === Board: $(BOARD) ..." 81 | 82 | check: 83 | $(if $(strip $(MODEL_PATH)), @echo " === Model path: $(MODEL_PATH)", $(error MODEL_PATH must be set and point at your model implementation generated with the TVM compiler)) 84 | @if [ ! -d "$(MODEL_PATH)" ]; then \ 85 | echo "$(MODEL_PATH) does not exist!"; \ 86 | exit 1; \ 87 | fi 88 | 89 | info: 90 | $(MAKE) -f $(BOARDS_DIR)/makefile.$(BOARD) info BUILD_DIR=$(BUILD_DIR) APP_NAME=$(APP_NAME) 91 | 92 | perf: check 93 | @echo " === Perf: Building from TVM sources ..." 94 | $(MAKE) -f $(BOARDS_DIR)/makefile.$(BOARD) CONFIG=$(LDCONF) BUILD_DIR=$(BUILD_DIR) APP_NAME=$(APP_NAME) 95 | 96 | valid: debug check 97 | @echo " === Validation: Building from TVM sources ..." 98 | $(MAKE) -f $(BOARDS_DIR)/makefile.$(BOARD) VALID=1 CONFIG=$(LDCONF) BUILD_DIR=$(BUILD_DIR) APP_NAME=$(APP_NAME) 99 | 100 | ####################################### 101 | # clean up 102 | ####################################### 103 | 104 | clean: app.clean 105 | 106 | app.clean: 107 | @echo -e "I: Cleaning APP build directory (${BUILD_DIR}/*)..." 108 | ${q}rm -rf $(BUILD_DIR) 109 | 110 | clean_nn: 111 | -rm $(BUILD_DIR)/network.* 112 | -rm $(BUILD_DIR)/network_data.* 113 | -rm $(BUILD_DIR)/network_lib.* 114 | 115 | ####################################### 116 | # flash 117 | ####################################### 118 | 119 | flash: $(BUILD_DIR)/$(APP_NAME).elf 120 | ${STM32_PROG} -c port=swd sn=${SERIAL_NUMBER} mode=UR reset=HWrst -d $(BUILD_DIR)/$(APP_NAME).elf -s 121 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Report potential product security vulnerabilities 2 | 3 | ST places a high priority on security, and our Product Security Incident Response Team (PSIRT) is committed to rapidly addressing potential security vulnerabilities affecting our products. PSIRT's long history and vast experience in security allows ST to perform clear analyses and provide appropriate guidance on mitigations and solutions when applicable. 4 | 5 | If you wish to report potential security vulnerabilities regarding our products, **please do not report them through public GitHub issues.** Instead, we encourage you to report them to our ST PSIRT following the process described at: **https://www.st.com/content/st_com/en/security/report-vulnerabilities.html** 6 | 7 | 8 | 9 | ### IMPORTANT - READ CAREFULLY: 10 | 11 | STMicroelectronics International N.V., on behalf of itself, its affiliates and subsidiaries, (collectively “ST”) takes all potential security vulnerability reports or other related communications (“Report(s)”) seriously. In order to review Your Report (the terms “You” and “Yours” include your employer, and all affiliates, subsidiaries and related persons or entities) and take actions as deemed appropriate, ST requires that we have the rights and Your permission to do so. 12 | 13 | As such, by submitting Your Report to ST, You agree that You have the right to do so, and You grant to ST the rights to use the Report for purposes related to security vulnerability analysis, testing, correction, patching, reporting and any other related purpose or function. 14 | 15 | By submitting Your Report, You agree that ST’s [Privacy Policy](https://www.st.com/content/st_com/en/common/privacy-portal.html) applies to all related communications. 16 | -------------------------------------------------------------------------------- /Src/Misc/aiTestTvmHelper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file aiTestTvmHelper.c 15 | * \brief STM32 TVM Helper functions for STM32 AI test application 16 | */ 17 | 18 | /* 19 | * Description: 20 | * 21 | * 22 | * History: 23 | * - v1.0 - Initial version 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | // ================================================== 32 | // aiPlatformVersion 33 | // ================================================== 34 | void aiPlatformVersion (void) 35 | { 36 | printf("\r\nAI platform (API %d.%d.%d - RUNTIME %d.%d.%d)\r\n", 37 | AI_PLATFORM_API_MAJOR, 38 | AI_PLATFORM_API_MINOR, 39 | AI_PLATFORM_API_MICRO, 40 | AI_PLATFORM_RUNTIME_MAJOR, 41 | AI_PLATFORM_RUNTIME_MINOR, 42 | AI_PLATFORM_RUNTIME_MICRO); 43 | } 44 | 45 | // ================================================== 46 | // aiLogErr 47 | // ================================================== 48 | void aiLogErr(const char *fct, const char * err) 49 | { 50 | if (fct) { 51 | printf("E: AI error: %s - %s\r\n", fct, err); 52 | } 53 | else { 54 | printf("E: AI error - %s\r\n", err); 55 | } 56 | } 57 | 58 | // ================================================== 59 | // aiPrintLayoutBuffer 60 | // ================================================== 61 | 62 | const char* _tvm_to_str(DLDataType dtype) 63 | { 64 | if (dtype.code == kDLBfloat) 65 | return "kDLBfloat"; 66 | if (dtype.code == kDLFloat) 67 | return "kDLFloat"; 68 | else if (dtype.code == kDLUInt) 69 | return "kDLUInt"; 70 | else if (dtype.code == kDLInt) 71 | return "kDLInt"; 72 | else 73 | return "??"; 74 | } 75 | 76 | 77 | void aiPrintLayoutBuffer (const char *msg, int idx, ai_tensor *tensor) 78 | { 79 | DLTensor * dltensor = &tensor->dltensor; 80 | DLDataType dtype = dltensor->dtype; 81 | 82 | printf("%s[%d] ", msg, idx); 83 | 84 | /* Data type/format */ 85 | printf(" %s/%ubits(%u)", _tvm_to_str(dtype), dtype.bits, dtype.lanes); 86 | 87 | /* meta data */ 88 | if (tensor->quant != NULL) { 89 | const ai_quantization_info* info = tensor->quant; 90 | printf(", scale=%f zp=%d (%d)", *info->scale, *(int *)info->zero_point, (int)info->dim); 91 | } 92 | 93 | /* shape/size and @ */ 94 | int32_t size = get_tensor_size (tensor); 95 | printf(", %ld bytes, shape=(", size); 96 | for (int i = 0; i < dltensor->ndim; ++i) { 97 | if (i != 0) 98 | printf(", "); 99 | printf("%d", (int)dltensor->shape[i]); 100 | } 101 | printf("), (0x%08x)\r\n", (unsigned int)dltensor->data); 102 | } 103 | 104 | // ================================================== 105 | // aiPrintNetworkInfo 106 | // ================================================== 107 | void aiPrintNetworkInfo(ai_model_info *nn, ai_handle hdl) 108 | { 109 | const char *name = nn->name; 110 | const char *datetime = nn->datetime; 111 | const char *revision = nn->revision; 112 | const char *tool_version = nn->tool_version; 113 | 114 | uint32_t n_nodes = nn->n_nodes; 115 | uint32_t n_inputs = nn->n_inputs; 116 | uint32_t n_outputs = nn->n_outputs; 117 | 118 | uint32_t act_size = nn->activations_size; 119 | uint32_t params_size = nn->params_size; 120 | 121 | ai_ptr params_addr = 0; 122 | ai_ptr act_addr = 0; 123 | 124 | if (hdl) { 125 | params_addr = ai_get_params(hdl); 126 | act_addr = ai_get_activations(hdl); 127 | } 128 | 129 | printf("\r\nNetwork configuration\r\n"); 130 | printf(" Model name : %s\r\n", name); 131 | printf(" Compile datetime : %s\r\n", datetime); 132 | printf(" Tool version : %s (%s)\r\n", tool_version, revision); 133 | 134 | printf("\r\nNetwork info\r\n"); 135 | printf(" nodes : %ld\r\n", n_nodes); 136 | printf(" activation : %ld bytes", act_size); 137 | if (act_addr) 138 | printf(" (0x%08x)\r\n", (int)act_addr); 139 | else 140 | printf(" - not initialized\r\n"); 141 | printf(" params : %ld bytes", params_size); 142 | if (params_addr) 143 | printf(" (0x%08x)\r\n", (int)params_addr); 144 | else 145 | printf(" - not initialized\r\n"); 146 | printf(" inputs/outputs : %lu/%lu\r\n", n_inputs, n_outputs); 147 | 148 | if (hdl == NULL) 149 | return; 150 | 151 | for (int i = 0; i < n_inputs; i++) { 152 | ai_tensor *input = ai_get_input(hdl, i); 153 | aiPrintLayoutBuffer(" I", i, input); 154 | } 155 | 156 | for (int i = 0; i < n_outputs; i++) { 157 | ai_tensor *output = ai_get_output(hdl, i); 158 | aiPrintLayoutBuffer(" O", i, output); 159 | } 160 | } 161 | 162 | 163 | #if defined(NO_X_CUBE_AI_RUNTIME) && NO_X_CUBE_AI_RUNTIME == 1 164 | 165 | #include "aiPbMgr.h" 166 | #include 167 | 168 | static ai_buffer_format set_ai_buffer_format(DLDataType dtype) 169 | { 170 | if ((dtype.code == kDLFloat) && (dtype.bits == 32)) 171 | return AI_BUFFER_FORMAT_FLOAT; 172 | if ((dtype.code == kDLUInt) && (dtype.bits == 8)) 173 | return AI_BUFFER_FORMAT_U8; 174 | if ((dtype.code == kDLInt) && (dtype.bits == 8)) 175 | return AI_BUFFER_FORMAT_S8; 176 | return AI_BUFFER_FORMAT_NONE; 177 | } 178 | 179 | static void set_ai_buffer(ai_tensor *tensor, ai_buffer* to_) 180 | { 181 | DLTensor * dltensor = &tensor->dltensor; 182 | DLDataType dtype = dltensor->dtype; 183 | 184 | struct ai_buffer_ext *eto_ = (struct ai_buffer_ext *)to_; 185 | 186 | to_->n_batches = dltensor->shape[0]; 187 | 188 | if (dltensor->ndim == 2) { 189 | to_->height = 1; 190 | to_->width = 1; 191 | to_->channels = dltensor->shape[1]; 192 | } 193 | else if (dltensor->ndim == 3) { 194 | to_->height = dltensor->shape[1]; 195 | to_->width = 1; 196 | to_->channels = dltensor->shape[2]; 197 | } 198 | else if (dltensor->ndim == 4) { 199 | to_->height = dltensor->shape[1]; 200 | to_->width = dltensor->shape[2]; 201 | to_->channels = dltensor->shape[3]; 202 | } 203 | 204 | to_->data = (ai_handle)dltensor->data; 205 | to_->format = set_ai_buffer_format(dtype); 206 | to_->meta_info = NULL; 207 | 208 | if (tensor->quant != NULL) { 209 | const ai_quantization_info* info = tensor->quant; 210 | eto_->buffer.meta_info = (ai_buffer_meta_info *)&eto_->extra; 211 | eto_->extra.scale = *info->scale; 212 | eto_->extra.zero_point = *info->zero_point; 213 | } 214 | 215 | return; 216 | } 217 | 218 | void aiTvmToReport(ai_model_info *nn, ai_handle hdl, ai_network_report *report) 219 | { 220 | const char *name = nn->name; 221 | const char *datetime = nn->datetime; 222 | const char *revision = nn->revision; 223 | //const char *tool_version = nn->tool_version; 224 | 225 | uint32_t n_nodes = nn->n_nodes; 226 | uint32_t n_inputs = nn->n_inputs; 227 | uint32_t n_outputs = nn->n_outputs; 228 | 229 | uint32_t act_size = nn->activations_size; 230 | uint32_t params_size = nn->params_size; 231 | 232 | size_t size; 233 | 234 | const char *_null = "NULL"; 235 | 236 | ai_platform_version _version_api = { AI_PLATFORM_API_MAJOR, 237 | AI_PLATFORM_API_MINOR, 238 | AI_PLATFORM_API_MICRO, 0 }; 239 | ai_platform_version _version_rt = { AI_PLATFORM_RUNTIME_MAJOR, 240 | AI_PLATFORM_RUNTIME_MINOR, 241 | AI_PLATFORM_RUNTIME_MICRO, 0}; 242 | ai_platform_version _version_null = {0, 0, 0, 0 }; 243 | 244 | const ai_buffer _def_buffer = { AI_BUFFER_FORMAT_U8, 1, 1, 2, 1, NULL, NULL }; 245 | 246 | report->model_name = name; 247 | report->model_signature = _null; 248 | report->model_datetime = datetime; 249 | report->compile_datetime = __DATE__ " " __TIME__; 250 | report->runtime_revision = revision; 251 | report->tool_revision = "TVM"; 252 | 253 | report->runtime_version = _version_rt; 254 | report->tool_version = _version_api; 255 | 256 | report->tool_api_version = _version_null; 257 | report->api_version = _version_null; 258 | report->interface_api_version = _version_null; 259 | 260 | report->n_macc = 1; 261 | 262 | report->n_inputs = n_inputs; 263 | size = report->n_inputs * sizeof(struct ai_buffer_ext); 264 | report->inputs = (ai_buffer *)malloc(size); 265 | for (int idx=0; idxn_inputs; idx++) { 266 | ai_tensor *input = ai_get_input(hdl, idx); 267 | set_ai_buffer(input, &report->inputs[idx]); 268 | } 269 | 270 | report->n_outputs = n_outputs; 271 | size = report->n_outputs * sizeof(struct ai_buffer_ext); 272 | report->outputs = (ai_buffer *)malloc(size); 273 | for (int idx=0; idxn_outputs; idx++) { 274 | ai_tensor *output = ai_get_output(hdl, idx); 275 | set_ai_buffer(output, &report->outputs[idx]); 276 | } 277 | 278 | report->n_nodes = n_nodes; 279 | report->signature = (ai_signature)0; 280 | 281 | report->activations = _def_buffer; 282 | report->activations.channels = (int)act_size; 283 | report->params = _def_buffer; 284 | report->params.channels = (int)params_size; 285 | } 286 | 287 | #endif 288 | -------------------------------------------------------------------------------- /Src/Validation/aiPbIO.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file aiPbIO.c 15 | * \brief Low Level nano PB stack functions 16 | */ 17 | 18 | /* System headers */ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | 35 | #define _PACKET_PAYLOAD_IN_SIZE (EnumLowLevelIO_IO_IN_PACKET_SIZE) 36 | 37 | static struct o_packet { 38 | uint8_t pw; 39 | uint8_t payload[_PACKET_PAYLOAD_IN_SIZE]; 40 | } o_packet; 41 | 42 | static bool write_packet(void) { 43 | return ioRawWriteBuffer((uint8_t *)&o_packet, _PACKET_PAYLOAD_IN_SIZE + 1); 44 | } 45 | 46 | void pb_io_flush_ostream(void) 47 | { 48 | o_packet.pw |= (1 << 7); /* Indicate last packet */ 49 | write_packet(); 50 | o_packet.pw = 0; 51 | } 52 | 53 | static bool write_callback(pb_ostream_t *stream, const uint8_t *buf, 54 | size_t count) 55 | { 56 | bool res = true; 57 | uint8_t *pr = (uint8_t *)buf; 58 | 59 | UNUSED(stream); 60 | 61 | while (count) { 62 | for (; o_packet.pw < _PACKET_PAYLOAD_IN_SIZE && count; o_packet.pw++) { 63 | o_packet.payload[o_packet.pw] = *pr; 64 | pr++; 65 | count--; 66 | } 67 | if (o_packet.pw == _PACKET_PAYLOAD_IN_SIZE) { 68 | res = write_packet(); 69 | o_packet.pw = 0; 70 | } 71 | } 72 | return res; 73 | } 74 | 75 | 76 | #define _PACKET_PAYLOAD_OUT_SIZE (EnumLowLevelIO_IO_OUT_PACKET_SIZE) 77 | 78 | static struct i_packet { 79 | uint8_t pr; 80 | uint8_t payload[_PACKET_PAYLOAD_OUT_SIZE]; 81 | } i_packet; 82 | 83 | static int i_ridx = 0; 84 | 85 | static bool read_packet(void) { 86 | bool res = ioRawReadBuffer((uint8_t *)&i_packet, 87 | _PACKET_PAYLOAD_OUT_SIZE + 1); 88 | i_ridx = 0; 89 | return res; 90 | } 91 | 92 | void pb_io_flush_istream(void) 93 | { 94 | i_packet.pr = 0xFF; 95 | i_ridx = 0; 96 | } 97 | 98 | static bool read_callback(pb_istream_t *stream, uint8_t *buf, size_t count) 99 | { 100 | bool res = true; 101 | uint8_t *pw = (uint8_t *)buf; 102 | 103 | UNUSED(stream); 104 | 105 | if (count == 0) 106 | return true; 107 | 108 | if (i_packet.pr == 0xFF) 109 | res = read_packet(); 110 | 111 | if (res == false) 112 | return res; 113 | 114 | while (count) { 115 | for (; i_packet.pr > 0 && count; i_packet.pr--) { 116 | *pw = i_packet.payload[i_ridx]; 117 | pw++; 118 | count--; 119 | i_ridx++; 120 | } 121 | if (count && i_packet.pr == 0) { 122 | uint8_t sync = 0xAA; 123 | ioRawWriteBuffer(&sync, 1); 124 | read_packet(); 125 | } 126 | } 127 | 128 | return res; 129 | } 130 | 131 | pb_ostream_t pb_io_ostream(int fd) 132 | { 133 | pb_ostream_t stream = {&write_callback, (void*)(intptr_t)fd, SIZE_MAX, 0}; 134 | return stream; 135 | } 136 | 137 | pb_istream_t pb_io_istream(int fd) 138 | { 139 | pb_istream_t stream = {&read_callback, (void*)(intptr_t)fd, SIZE_MAX}; 140 | return stream; 141 | } 142 | 143 | int pb_io_stream_init(void) 144 | { 145 | ioRawDisableLLWrite(); 146 | return 0; 147 | } 148 | -------------------------------------------------------------------------------- /Src/Validation/pb_common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 Petteri Aimonen 3 | * 4 | * This software is provided 'as-is', without any express or 5 | * implied warranty. In no event will the authors be held liable 6 | * for any damages arising from the use of this software. 7 | * 8 | * Permission is granted to anyone to use this software for any 9 | * purpose, including commercial applications, and to alter it and 10 | * redistribute it freely, subject to the following restrictions: 11 | * 12 | * 1. The origin of this software must not be misrepresented; you 13 | * must not claim that you wrote the original software. If you use 14 | * this software in a product, an acknowledgment in the product 15 | * documentation would be appreciated but is not required. 16 | * 17 | * 2. Altered source versions must be plainly marked as such, and 18 | * must not be misrepresented as being the original software. 19 | * 20 | * 3. This notice may not be removed or altered from any source 21 | * distribution. 22 | */ 23 | 24 | /* 25 | * Included from: https://github.com/nanopb/nanopb/ 26 | */ 27 | 28 | /*! 29 | * \file pb_common.c 30 | * \brief Common support functions for pb_encode.c and pb_decode.c. 31 | * 2014 Petteri Aimonen 32 | */ 33 | 34 | #include "pb_common.h" 35 | 36 | bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct) 37 | { 38 | iter->start = fields; 39 | iter->pos = fields; 40 | iter->required_field_index = 0; 41 | iter->dest_struct = dest_struct; 42 | iter->pData = (char*)dest_struct + iter->pos->data_offset; 43 | iter->pSize = (char*)iter->pData + iter->pos->size_offset; 44 | 45 | return (iter->pos->tag != 0); 46 | } 47 | 48 | bool pb_field_iter_next(pb_field_iter_t *iter) 49 | { 50 | const pb_field_t *prev_field = iter->pos; 51 | 52 | if (prev_field->tag == 0) 53 | { 54 | /* Handle empty message types, where the first field is already the terminator. 55 | * In other cases, the iter->pos never points to the terminator. */ 56 | return false; 57 | } 58 | 59 | iter->pos++; 60 | 61 | if (iter->pos->tag == 0) 62 | { 63 | /* Wrapped back to beginning, reinitialize */ 64 | (void)pb_field_iter_begin(iter, iter->start, iter->dest_struct); 65 | return false; 66 | } 67 | else 68 | { 69 | /* Increment the pointers based on previous field size */ 70 | size_t prev_size = prev_field->data_size; 71 | 72 | if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF && 73 | PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF && 74 | iter->pos->data_offset == PB_SIZE_MAX) 75 | { 76 | /* Don't advance pointers inside unions */ 77 | return true; 78 | } 79 | else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC && 80 | PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED) 81 | { 82 | /* In static arrays, the data_size tells the size of a single entry and 83 | * array_size is the number of entries */ 84 | prev_size *= prev_field->array_size; 85 | } 86 | else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER) 87 | { 88 | /* Pointer fields always have a constant size in the main structure. 89 | * The data_size only applies to the dynamically allocated area. */ 90 | prev_size = sizeof(void*); 91 | } 92 | 93 | if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED) 94 | { 95 | /* Count the required fields, in order to check their presence in the 96 | * decoder. */ 97 | iter->required_field_index++; 98 | } 99 | 100 | iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset; 101 | iter->pSize = (char*)iter->pData + iter->pos->size_offset; 102 | return true; 103 | } 104 | } 105 | 106 | bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) 107 | { 108 | const pb_field_t *start = iter->pos; 109 | 110 | do { 111 | if (iter->pos->tag == tag && 112 | PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION) 113 | { 114 | /* Found the wanted field */ 115 | return true; 116 | } 117 | 118 | (void)pb_field_iter_next(iter); 119 | } while (iter->pos != start); 120 | 121 | /* Searched all the way back to start, and found nothing. */ 122 | return false; 123 | } 124 | 125 | 126 | -------------------------------------------------------------------------------- /Src/Validation/stm32msg.pb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file stm32msg.pb.c 15 | * \brief Automatically generated nanopb constant definitions. 16 | * Generated by nanopb-0.3.9.1 at Thu Sep 12 09:14:47 2019. 17 | */ 18 | 19 | #include "stm32msg.pb.h" 20 | 21 | /* @@protoc_insertion_point(includes) */ 22 | #if PB_PROTO_HEADER_VERSION != 30 23 | #error Regenerate this file with the current version of nanopb generator. 24 | #endif 25 | 26 | const EnumCmd reqMsg_cmd_default = EnumCmd_CMD_SYS_INFO; 27 | const uint32_t aiBufferShapeMsg_format_default = 0u; 28 | const uint32_t aiBufferShapeMsg_n_batches_default = 1u; 29 | const uint32_t aiBufferShapeMsg_height_default = 1u; 30 | const uint32_t aiBufferShapeMsg_width_default = 1u; 31 | const uint32_t aiBufferShapeMsg_channels_default = 1u; 32 | const float aiBufferShapeMsg_scale_default = 0; 33 | const int32_t aiBufferShapeMsg_zeropoint_default = 0; 34 | 35 | 36 | const pb_field_t reqMsg_fields[6] = { 37 | PB_FIELD( 1, UINT32 , REQUIRED, STATIC , FIRST, reqMsg, reqid, reqid, 0), 38 | PB_FIELD( 2, UENUM , REQUIRED, STATIC , OTHER, reqMsg, cmd, reqid, &reqMsg_cmd_default), 39 | PB_FIELD( 3, UINT32 , REQUIRED, STATIC , OTHER, reqMsg, param, cmd, 0), 40 | PB_FIELD( 4, STRING , REQUIRED, STATIC , OTHER, reqMsg, name, param, 0), 41 | PB_FIELD( 5, UINT32 , REQUIRED, STATIC , OTHER, reqMsg, opt, name, 0), 42 | PB_LAST_FIELD 43 | }; 44 | 45 | const pb_field_t aiRunReportMsg_fields[6] = { 46 | PB_FIELD( 1, UINT32 , REQUIRED, STATIC , FIRST, aiRunReportMsg, id, id, 0), 47 | PB_FIELD( 2, UINT32 , REQUIRED, STATIC , OTHER, aiRunReportMsg, signature, id, 0), 48 | PB_FIELD( 3, UINT32 , REQUIRED, STATIC , OTHER, aiRunReportMsg, num_inferences, signature, 0), 49 | PB_FIELD( 4, UINT32 , REQUIRED, STATIC , OTHER, aiRunReportMsg, n_nodes, num_inferences, 0), 50 | PB_FIELD( 5, FLOAT , REQUIRED, STATIC , OTHER, aiRunReportMsg, elapsed_ms, n_nodes, 0), 51 | PB_LAST_FIELD 52 | }; 53 | 54 | const pb_field_t aiBufferShapeMsg_fields[8] = { 55 | PB_FIELD( 1, UINT32 , REQUIRED, STATIC , FIRST, aiBufferShapeMsg, format, format, &aiBufferShapeMsg_format_default), 56 | PB_FIELD( 2, UINT32 , REQUIRED, STATIC , OTHER, aiBufferShapeMsg, n_batches, format, &aiBufferShapeMsg_n_batches_default), 57 | PB_FIELD( 3, UINT32 , REQUIRED, STATIC , OTHER, aiBufferShapeMsg, height, n_batches, &aiBufferShapeMsg_height_default), 58 | PB_FIELD( 4, UINT32 , REQUIRED, STATIC , OTHER, aiBufferShapeMsg, width, height, &aiBufferShapeMsg_width_default), 59 | PB_FIELD( 5, UINT32 , REQUIRED, STATIC , OTHER, aiBufferShapeMsg, channels, width, &aiBufferShapeMsg_channels_default), 60 | PB_FIELD( 6, FLOAT , REQUIRED, STATIC , OTHER, aiBufferShapeMsg, scale, channels, &aiBufferShapeMsg_scale_default), 61 | PB_FIELD( 7, INT32 , REQUIRED, STATIC , OTHER, aiBufferShapeMsg, zeropoint, scale, &aiBufferShapeMsg_zeropoint_default), 62 | PB_LAST_FIELD 63 | }; 64 | 65 | const pb_field_t aiNetworkInfoMsg_fields[21] = { 66 | PB_FIELD( 1, STRING , REQUIRED, STATIC , FIRST, aiNetworkInfoMsg, model_name, model_name, 0), 67 | PB_FIELD( 2, STRING , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, model_signature, model_name, 0), 68 | PB_FIELD( 3, STRING , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, model_datetime, model_signature, 0), 69 | PB_FIELD( 4, STRING , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, compile_datetime, model_datetime, 0), 70 | PB_FIELD( 5, STRING , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, runtime_revision, compile_datetime, 0), 71 | PB_FIELD( 6, UINT32 , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, runtime_version, runtime_revision, 0), 72 | PB_FIELD( 7, STRING , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, tool_revision, runtime_version, 0), 73 | PB_FIELD( 8, UINT32 , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, tool_version, tool_revision, 0), 74 | PB_FIELD( 9, UINT32 , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, tool_api_version, tool_version, 0), 75 | PB_FIELD( 10, UINT32 , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, api_version, tool_api_version, 0), 76 | PB_FIELD( 11, UINT32 , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, interface_api_version, api_version, 0), 77 | PB_FIELD( 12, UINT32 , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, n_macc, interface_api_version, 0), 78 | PB_FIELD( 13, UINT32 , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, n_inputs, n_macc, 0), 79 | PB_FIELD( 14, UINT32 , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, n_outputs, n_inputs, 0), 80 | PB_FIELD( 15, UINT32 , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, n_nodes, n_outputs, 0), 81 | PB_FIELD( 16, MESSAGE , REPEATED, CALLBACK, OTHER, aiNetworkInfoMsg, inputs, n_nodes, &aiBufferShapeMsg_fields), 82 | PB_FIELD( 17, MESSAGE , REPEATED, CALLBACK, OTHER, aiNetworkInfoMsg, outputs, inputs, &aiBufferShapeMsg_fields), 83 | PB_FIELD( 18, MESSAGE , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, activations, outputs, &aiBufferShapeMsg_fields), 84 | PB_FIELD( 19, MESSAGE , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, weights, activations, &aiBufferShapeMsg_fields), 85 | PB_FIELD( 20, UINT32 , REQUIRED, STATIC , OTHER, aiNetworkInfoMsg, signature, weights, 0), 86 | PB_LAST_FIELD 87 | }; 88 | 89 | const pb_field_t aiBufferByteMsg_fields[3] = { 90 | PB_FIELD( 1, MESSAGE , REQUIRED, STATIC , FIRST, aiBufferByteMsg, shape, shape, &aiBufferShapeMsg_fields), 91 | PB_FIELD( 2, BYTES , REQUIRED, CALLBACK, OTHER, aiBufferByteMsg, datas, shape, 0), 92 | PB_LAST_FIELD 93 | }; 94 | 95 | const pb_field_t syncMsg_fields[3] = { 96 | PB_FIELD( 1, UINT32 , REQUIRED, STATIC , FIRST, syncMsg, version, version, 0), 97 | PB_FIELD( 4, UINT32 , REQUIRED, STATIC , OTHER, syncMsg, capability, version, 0), 98 | PB_LAST_FIELD 99 | }; 100 | 101 | const pb_field_t sysinfoMsg_fields[5] = { 102 | PB_FIELD( 1, UINT32 , REQUIRED, STATIC , FIRST, sysinfoMsg, devid, devid, 0), 103 | PB_FIELD( 2, UINT32 , REQUIRED, STATIC , OTHER, sysinfoMsg, sclock, devid, 0), 104 | PB_FIELD( 3, UINT32 , REQUIRED, STATIC , OTHER, sysinfoMsg, hclock, sclock, 0), 105 | PB_FIELD( 4, UINT32 , REQUIRED, STATIC , OTHER, sysinfoMsg, cache, hclock, 0), 106 | PB_LAST_FIELD 107 | }; 108 | 109 | const pb_field_t ackMsg_fields[3] = { 110 | PB_FIELD( 1, UINT32 , REQUIRED, STATIC , FIRST, ackMsg, param, param, 0), 111 | PB_FIELD( 2, UENUM , REQUIRED, STATIC , OTHER, ackMsg, error, param, 0), 112 | PB_LAST_FIELD 113 | }; 114 | 115 | const pb_field_t logMsg_fields[3] = { 116 | PB_FIELD( 1, UINT32 , REQUIRED, STATIC , FIRST, logMsg, level, level, 0), 117 | PB_FIELD( 2, STRING , REQUIRED, STATIC , OTHER, logMsg, str, level, 0), 118 | PB_LAST_FIELD 119 | }; 120 | 121 | const pb_field_t nodeMsg_fields[5] = { 122 | PB_FIELD( 1, UINT32 , REQUIRED, STATIC , FIRST, nodeMsg, type, type, 0), 123 | PB_FIELD( 2, UINT32 , REQUIRED, STATIC , OTHER, nodeMsg, id, type, 0), 124 | PB_FIELD( 3, FLOAT , REQUIRED, STATIC , OTHER, nodeMsg, duration, id, 0), 125 | PB_FIELD( 4, MESSAGE , REQUIRED, STATIC , OTHER, nodeMsg, buffer, duration, &aiBufferByteMsg_fields), 126 | PB_LAST_FIELD 127 | }; 128 | 129 | const pb_field_t respMsg_fields[10] = { 130 | PB_FIELD( 1, UINT32 , REQUIRED, STATIC , FIRST, respMsg, reqid, reqid, 0), 131 | PB_FIELD( 2, UENUM , REQUIRED, STATIC , OTHER, respMsg, state, reqid, 0), 132 | PB_ONEOF_FIELD(payload, 10, MESSAGE , ONEOF, STATIC , OTHER, respMsg, sync, state, &syncMsg_fields), 133 | PB_ONEOF_FIELD(payload, 11, MESSAGE , ONEOF, STATIC , UNION, respMsg, sinfo, state, &sysinfoMsg_fields), 134 | PB_ONEOF_FIELD(payload, 12, MESSAGE , ONEOF, STATIC , UNION, respMsg, ack, state, &ackMsg_fields), 135 | PB_ONEOF_FIELD(payload, 13, MESSAGE , ONEOF, STATIC , UNION, respMsg, log, state, &logMsg_fields), 136 | PB_ONEOF_FIELD(payload, 14, MESSAGE , ONEOF, STATIC , UNION, respMsg, node, state, &nodeMsg_fields), 137 | PB_ONEOF_FIELD(payload, 20, MESSAGE , ONEOF, STATIC , UNION, respMsg, ninfo, state, &aiNetworkInfoMsg_fields), 138 | PB_ONEOF_FIELD(payload, 21, MESSAGE , ONEOF, STATIC , UNION, respMsg, report, state, &aiRunReportMsg_fields), 139 | PB_LAST_FIELD 140 | }; 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | /* Check that field information fits in pb_field_t */ 152 | #if !defined(PB_FIELD_32BIT) 153 | /* If you get an error here, it means that you need to define PB_FIELD_32BIT 154 | * compile-time option. You can do that in pb.h or on compiler command line. 155 | * 156 | * The reason you need to do this is that some of your messages contain tag 157 | * numbers or field sizes that are larger than what can fit in 8 or 16 bit 158 | * field descriptors. 159 | */ 160 | PB_STATIC_ASSERT((pb_membersize(aiNetworkInfoMsg, activations) < 65536 && pb_membersize(aiNetworkInfoMsg, weights) < 65536 && pb_membersize(aiBufferByteMsg, shape) < 65536 && pb_membersize(nodeMsg, buffer) < 65536 && pb_membersize(respMsg, payload.sync) < 65536 && pb_membersize(respMsg, payload.sinfo) < 65536 && pb_membersize(respMsg, payload.ack) < 65536 && pb_membersize(respMsg, payload.log) < 65536 && pb_membersize(respMsg, payload.node) < 65536 && pb_membersize(respMsg, payload.ninfo) < 65536 && pb_membersize(respMsg, payload.report) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_reqMsg_aiRunReportMsg_aiBufferShapeMsg_aiNetworkInfoMsg_aiBufferByteMsg_syncMsg_sysinfoMsg_ackMsg_logMsg_nodeMsg_respMsg) 161 | #endif 162 | 163 | #if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) 164 | /* If you get an error here, it means that you need to define PB_FIELD_16BIT 165 | * compile-time option. You can do that in pb.h or on compiler command line. 166 | * 167 | * The reason you need to do this is that some of your messages contain tag 168 | * numbers or field sizes that are larger than what can fit in the default 169 | * 8 bit descriptors. 170 | */ 171 | PB_STATIC_ASSERT((pb_membersize(aiNetworkInfoMsg, activations) < 256 && pb_membersize(aiNetworkInfoMsg, weights) < 256 && pb_membersize(aiBufferByteMsg, shape) < 256 && pb_membersize(nodeMsg, buffer) < 256 && pb_membersize(respMsg, payload.sync) < 256 && pb_membersize(respMsg, payload.sinfo) < 256 && pb_membersize(respMsg, payload.ack) < 256 && pb_membersize(respMsg, payload.log) < 256 && pb_membersize(respMsg, payload.node) < 256 && pb_membersize(respMsg, payload.ninfo) < 256 && pb_membersize(respMsg, payload.report) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_reqMsg_aiRunReportMsg_aiBufferShapeMsg_aiNetworkInfoMsg_aiBufferByteMsg_syncMsg_sysinfoMsg_ackMsg_logMsg_nodeMsg_respMsg) 172 | #endif 173 | 174 | 175 | /* @@protoc_insertion_point(eof) */ 176 | -------------------------------------------------------------------------------- /Src/app_x-cube-ai.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /*! 14 | * \file app_x-cube-ai.c 15 | * \brief AI program body 16 | */ 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | #include 23 | #include "app_x-cube-ai.h" 24 | #include "bsp_ai.h" 25 | #ifdef USE_VALID 26 | #include "aiValidation.h" 27 | #else 28 | #include "aiSystemPerformance.h" 29 | #endif 30 | 31 | /* USER CODE BEGIN includes */ 32 | 33 | /* USER CODE END includes */ 34 | 35 | /************************************************************************* 36 | * 37 | */ 38 | void MX_X_CUBE_AI_Init(void) 39 | { 40 | MX_UARTx_Init(); 41 | #ifdef USE_VALID 42 | aiValidationInit(); 43 | #else 44 | aiSystemPerformanceInit(); 45 | #endif 46 | /* USER CODE BEGIN 0 */ 47 | /* USER CODE END 0 */ 48 | } 49 | 50 | void MX_X_CUBE_AI_Process(void) 51 | { 52 | #ifdef USE_VALID 53 | aiValidationProcess(); 54 | #else 55 | aiSystemPerformanceProcess(); 56 | #endif 57 | HAL_Delay(1000); /* delay 1s */ 58 | /* USER CODE BEGIN 1 */ 59 | /* USER CODE END 1 */ 60 | } 61 | -------------------------------------------------------------------------------- /Src/syscalls.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /** 14 | ***************************************************************************** 15 | ** 16 | ** File : syscalls.c 17 | ** 18 | ** Author : Auto-generated by STM32CubeIDE 19 | ** 20 | ** Abstract : STM32CubeIDE Minimal System calls file 21 | ** 22 | ** For more information about which c-functions 23 | ** need which of these lowlevel functions 24 | ** please consult the Newlib libc-manual 25 | ** 26 | ** Environment : STM32CubeIDE MCU 27 | ** 28 | ** Distribution: The file is distributed as is, without any warranty 29 | ** of any kind. 30 | ** 31 | ***************************************************************************** 32 | */ 33 | 34 | /* Includes */ 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | 45 | /* Variables */ 46 | //#undef errno 47 | extern int errno; 48 | extern int __io_putchar(int ch) __attribute__((weak)); 49 | extern int __io_getchar(void) __attribute__((weak)); 50 | 51 | register char * stack_ptr asm("sp"); 52 | 53 | char *__env[1] = { 0 }; 54 | char **environ = __env; 55 | 56 | 57 | /* Functions */ 58 | void initialise_monitor_handles() 59 | { 60 | } 61 | 62 | int _getpid(void) 63 | { 64 | return 1; 65 | } 66 | 67 | int _kill(int pid, int sig) 68 | { 69 | errno = EINVAL; 70 | return -1; 71 | } 72 | 73 | void _exit (int status) 74 | { 75 | _kill(status, -1); 76 | while (1) {} /* Make sure we hang here */ 77 | } 78 | 79 | __attribute__((weak)) int _read(int file, char *ptr, int len) 80 | { 81 | int DataIdx; 82 | 83 | for (DataIdx = 0; DataIdx < len; DataIdx++) 84 | { 85 | *ptr++ = __io_getchar(); 86 | } 87 | 88 | return len; 89 | } 90 | 91 | __attribute__((weak)) int _write(int file, char *ptr, int len) 92 | { 93 | int DataIdx; 94 | 95 | for (DataIdx = 0; DataIdx < len; DataIdx++) 96 | { 97 | __io_putchar(*ptr++); 98 | } 99 | return len; 100 | } 101 | 102 | int _close(int file) 103 | { 104 | return -1; 105 | } 106 | 107 | 108 | int _fstat(int file, struct stat *st) 109 | { 110 | st->st_mode = S_IFCHR; 111 | return 0; 112 | } 113 | 114 | int _isatty(int file) 115 | { 116 | return 1; 117 | } 118 | 119 | int _lseek(int file, int ptr, int dir) 120 | { 121 | return 0; 122 | } 123 | 124 | int _open(char *path, int flags, ...) 125 | { 126 | /* Pretend like we always fail */ 127 | return -1; 128 | } 129 | 130 | int _wait(int *status) 131 | { 132 | errno = ECHILD; 133 | return -1; 134 | } 135 | 136 | int _unlink(char *name) 137 | { 138 | errno = ENOENT; 139 | return -1; 140 | } 141 | 142 | int _times(struct tms *buf) 143 | { 144 | return -1; 145 | } 146 | 147 | int _stat(char *file, struct stat *st) 148 | { 149 | st->st_mode = S_IFCHR; 150 | return 0; 151 | } 152 | 153 | int _link(char *old, char *new) 154 | { 155 | errno = EMLINK; 156 | return -1; 157 | } 158 | 159 | int _fork(void) 160 | { 161 | errno = EAGAIN; 162 | return -1; 163 | } 164 | 165 | int _execve(char *name, char **argv, char **env) 166 | { 167 | errno = ENOMEM; 168 | return -1; 169 | } 170 | -------------------------------------------------------------------------------- /Src/sysmem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * @attention 3 | * 4 | * Copyright (c) 2022 STMicroelectronics. 5 | * All rights reserved. 6 | * 7 | * This software is licensed under terms that can be found in the LICENSE file 8 | * in the root directory of this software component. 9 | * If no LICENSE file comes with this software, it is provided AS-IS. 10 | * 11 | */ 12 | 13 | /** 14 | ***************************************************************************** 15 | ** 16 | ** File : sysmem.c 17 | ** 18 | ** Author : Auto-generated by STM32CubeIDE 19 | ** 20 | ** Abstract : STM32CubeIDE Minimal System Memory calls file 21 | ** 22 | ** For more information about which c-functions 23 | ** need which of these lowlevel functions 24 | ** please consult the Newlib libc-manual 25 | ** 26 | ** Environment : STM32CubeIDE MCU 27 | ** 28 | ** Distribution: The file is distributed as is, without any warranty 29 | ** of any kind. 30 | ** 31 | ***************************************************************************** 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | /** 39 | * Pointer to the current high watermark of the heap usage 40 | */ 41 | static uint8_t *__sbrk_heap_end = NULL; 42 | 43 | /* Functions */ 44 | 45 | /* 46 | https://github.com/ARMmbed/mbed-os/issues/1561 47 | */ 48 | 49 | extern __attribute__((weak)) uint32_t __HeapLimit; 50 | 51 | static const uint8_t * get_heap_limit() { 52 | 53 | if (&__HeapLimit) { 54 | return (unsigned char*) &__HeapLimit; 55 | } 56 | 57 | extern uint8_t _estack; /* Symbol defined in the linker script */ 58 | extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */ 59 | const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size; 60 | const uint8_t *max_heap = (uint8_t *)stack_limit; 61 | 62 | return max_heap; 63 | 64 | //#if defined(TARGET_ARM7) 65 | // return stack_ptr; 66 | //#elif !defined(TARGET_CORTEX_A) 67 | // return (unsigned char*)__get_MSP(); 68 | //#endif 69 | } 70 | 71 | /** 72 | * @brief _sbrk() allocates memory to the newlib heap and is used by malloc 73 | * and others from the C library 74 | * 75 | * @verbatim 76 | * ############################################################################ 77 | * # .data # .bss # newlib heap # MSP stack # 78 | * # # # # Reserved by _Min_Stack_Size # 79 | * ############################################################################ 80 | * ^-- RAM start ^-- _end _estack, RAM end --^ 81 | * @endverbatim 82 | * 83 | * This implementation starts allocating at the '_end' linker symbol 84 | * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack 85 | * The implementation considers '_estack' linker symbol to be RAM end 86 | * NOTE: If the MSP stack, at any point during execution, grows larger than the 87 | * reserved size, please increase the '_Min_Stack_Size'. 88 | * 89 | * @param incr Memory size 90 | * @return Pointer to allocated memory 91 | */ 92 | void *_sbrk(ptrdiff_t incr) 93 | { 94 | extern uint8_t _end; /* Symbol defined in the linker script */ 95 | const uint8_t *max_heap = get_heap_limit(); 96 | uint8_t *prev_heap_end; 97 | 98 | /* Initialize heap end at first call */ 99 | if (NULL == __sbrk_heap_end) 100 | { 101 | __sbrk_heap_end = &_end; 102 | } 103 | 104 | /* Protect heap from growing into the reserved MSP stack */ 105 | if (__sbrk_heap_end + incr > max_heap) 106 | { 107 | errno = ENOMEM; 108 | return (void *)-1; 109 | } 110 | 111 | prev_heap_end = __sbrk_heap_end; 112 | __sbrk_heap_end += incr; 113 | 114 | return (void *)prev_heap_end; 115 | } 116 | 117 | 118 | -------------------------------------------------------------------------------- /mk/common.mk: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | # Common Makefile rules for the STM32 microcontroller project. 13 | 14 | ifeq ($(strip $(CORE)),) 15 | $(error CORE is not defined) 16 | endif 17 | 18 | CFLAGS += ${CFLAGS-${CORE}} 19 | 20 | # APP Common options 21 | CFLAGS += -Wall 22 | CFLAGS += -fdata-sections -ffunction-sections -fstack-usage 23 | CFALGS += -std=gnu11 24 | CFLAGS += --specs=nano.specs 25 | CFLAGS += -DCHECK_STM32_FAMILY 26 | 27 | # APP DEBUG options 28 | _APP_DEBUG_OPT = -g3 29 | # _APP_DEBUG_OPT += -gdwarf-2 30 | 31 | ifeq ($(APP_DEBUG), 1) 32 | CFLAGS += ${_APP_DEBUG_OPT} -O0 -DDEBUG 33 | else 34 | CFLAGS += ${_APP_DEBUG_OPT} ${APP_OPTIM} -DNDEBUG 35 | endif 36 | 37 | # 38 | # Model sources 39 | # 40 | MODEL_PATH_NO_SLASH = $(realpath -s ${MODEL_PATH}) 41 | C_SOURCES += $(wildcard ${MODEL_PATH_NO_SLASH}/*.c) 42 | 43 | CFLAGS += -I$(MODEL_PATH) 44 | 45 | # 46 | # TVM files ----------------------------------------- 47 | # 48 | 49 | TVM_CRT_PATH = $(TVM_PATH)/src/runtime/crt/common 50 | STM32_RUNTIME_PATH = $(TVM_PATH)/src/runtime/crt/contrib/stm32 51 | 52 | CFLAGS += -DTLM_COUNTERS 53 | 54 | C_SOURCES += $(TVM_CRT_PATH)/crt_backend_api.c 55 | C_SOURCES += $(STM32_RUNTIME_PATH)/runtime.c 56 | C_SOURCES += $(STM32_RUNTIME_PATH)/ai_runtime_api.c 57 | 58 | CFLAGS += -I$(TVM_PATH)/include \ 59 | -I$(TVM_PATH)/3rdparty/dlpack/include \ 60 | -I$(TVM_PATH)/include/tvm/runtime \ 61 | -I$(STM32_RUNTIME_PATH) 62 | 63 | # 64 | # Application files ----------------------------------------- 65 | # 66 | 67 | C_SOURCES += ${ROOT_DIR}/Src/app_x-cube-ai.c 68 | 69 | C_SOURCES += ${ROOT_DIR}/Src/sysmem.c 70 | C_SOURCES += ${ROOT_DIR}/Src/syscalls.c 71 | 72 | # Extra USB_CDC support 73 | ifeq ($(strip $(USE_USB_CDC)),y) 74 | ifeq ($(strip $(USB_CDC_IS_AVAILABLE)), y) 75 | CFLAGS += -DUSE_USB_CDC_CLASS=1 76 | endif 77 | endif 78 | 79 | ifeq ($(VALID), 1) 80 | 81 | CFLAGS += -DUSE_VALID 82 | CFLAGS += -DAI_PB_TEST=1 83 | CFLAGS += -DNO_X_CUBE_AI_RUNTIME=1 84 | 85 | CFLAGS += -I${ROOT_DIR}/Inc/Validation 86 | CFLAGS += -I${ROOT_DIR}/Inc/Misc 87 | 88 | C_SOURCES += ${ROOT_DIR}/Src/Validation/aiPbMgr.c 89 | C_SOURCES += ${ROOT_DIR}/Src/Validation/aiPbIO.c 90 | 91 | C_SOURCES += ${ROOT_DIR}/Src/Validation/aiValidation.c 92 | 93 | C_SOURCES += ${ROOT_DIR}/Src/Validation/pb_common.c 94 | C_SOURCES += ${ROOT_DIR}/Src/Validation/pb_decode.c 95 | C_SOURCES += ${ROOT_DIR}/Src/Validation/pb_encode.c 96 | C_SOURCES += ${ROOT_DIR}/Src/Validation/stm32msg.pb.c 97 | 98 | else 99 | 100 | # 101 | # aiSysPerformance ----------------------------------------- 102 | # 103 | # Include specific files for aiSystemPerformance application 104 | 105 | CFLAGS += -I${ROOT_DIR}/Inc/SystemPerformance 106 | CFLAGS += -I${ROOT_DIR}/Inc/Misc 107 | 108 | C_SOURCES += ${ROOT_DIR}/Src/SystemPerformance/aiSystemPerformance.c 109 | 110 | endif 111 | 112 | C_SOURCES += ${ROOT_DIR}/Src/Misc/aiTestTvmHelper.c 113 | C_SOURCES += ${ROOT_DIR}/Src/Misc/aiTestUtility.c 114 | 115 | ifneq ($(strip $(BAUDRATE)),) 116 | CFLAGS += -DBAUDRATE=${BAUDRATE} 117 | endif 118 | 119 | # 120 | # C-STARTUP/HAL/BSP files ----------------------------------------- 121 | # 122 | HAL_DIR_ROOT = $(X_CUBE_PATH)/Drivers/${STM32}_HAL_Driver 123 | BSP_DIR_ROOT = $(X_CUBE_PATH)/Drivers/BSP 124 | CMSIS_DIR_ROOT = $(X_CUBE_PATH)/Drivers/CMSIS 125 | 126 | include ${BOARDS_DIR}/${BOARD}/files.mk 127 | 128 | CFLAGS += -I${ROOT_DIR}/Inc 129 | CFLAGS += -I${BOARDS_DIR}/${BOARD}/Inc 130 | 131 | # CMSIS 132 | CFLAGS += -I$(CMSIS_DIR_ROOT)/Include 133 | CFLAGS += -I$(CMSIS_DIR_ROOT)/Device/ST/${STM32}/Include 134 | 135 | # libraries 136 | 137 | LIBS = -lc -lm -lnosys 138 | #LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections 139 | LDFLAGS += $(LDFLAGS-$(CORE)) -specs=nano.specs $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(BOARD).map,--cref -Wl,--gc-sections 140 | LDFLAGS += -u _printf_float 141 | LDFLAGS += -Wl,--wrap=malloc -Wl,--wrap=free 142 | 143 | #LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(APP_NAME).map,--cref -Wl,--gc-sections -static 144 | ##LDFLAGS += -specs=nosys.specs -specs=nano.specs -lstdc++ -lsupc++ 145 | #LDFLAGS += -specs=nosys.specs -specs=nano.specs 146 | ##LDFLAGS += -Wl,--start-group -lc -lm -Wl,--end-group -Wl,--print-memory-usage 147 | #LDFLAGS += -Wl,--start-group -lc -lm -Wl,--end-group 148 | LDFLAGS += -Wl,--print-memory-usage 149 | 150 | 151 | # list of objects 152 | OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o))) 153 | vpath %.c $(sort $(dir $(C_SOURCES))) 154 | 155 | # list of ASM program objects 156 | OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o))) 157 | vpath %.s $(sort $(dir $(ASM_SOURCES))) 158 | 159 | ###################################### 160 | # target 161 | ###################################### 162 | 163 | .PHONY: all clean info flash app.clean 164 | 165 | all: $(BUILD_DIR) info.short $(BUILD_DIR)/$(APP_NAME).bin size 166 | 167 | $(BUILD_DIR)/$(APP_NAME).elf: $(OBJECTS) 168 | @mkdir -p $(@D) 169 | @echo "LD(${APP_NAME}) $@ (VALID=$(VALID))" 170 | ${q}$(CC) $(OBJECTS) $(LDFLAGS) -o $@ 171 | @echo "LIST(${APP_NAME}) $(BUILD_DIR)/$(APP_NAME).elf (VALID=$(VALID))" 172 | ${q}$(OBJDUMP) -h -S $(BUILD_DIR)/$(APP_NAME).elf > $(BUILD_DIR)/$(APP_NAME).list 173 | 174 | size: $(BUILD_DIR)/$(APP_NAME).elf 175 | @echo "SIZE(${APP_NAME}) $(BUILD_DIR)/$(APP_NAME).elf (VALID=$(VALID))" 176 | ${q}$(SIZE) $(BUILD_DIR)/$(APP_NAME).elf 177 | 178 | $(BUILD_DIR)/$(APP_NAME).bin: $(BUILD_DIR)/$(APP_NAME).elf 179 | @echo "OBJ(${APP_NAME}) $@" 180 | ${q}$(OBJCOPY) -O binary $(BUILD_DIR)/$(APP_NAME).elf $(BUILD_DIR)/$(APP_NAME).bin 181 | 182 | $(BUILD_DIR)/%.o: %.c 183 | $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@ 184 | 185 | $(BUILD_DIR)/%.o: %.s 186 | $(CC) -c $(CFLAGS) $< -o $@ 187 | 188 | $(BUILD_DIR): 189 | mkdir -p $@ 190 | 191 | info.short: 192 | @echo "I: Building AI test APP for STM32=${STM32} (APP_DEBUG=${APP_DEBUG})" 193 | @echo "I: TOOLS_DIR=${_TOOLS_DIR}" 194 | 195 | info: info.short 196 | @echo "----------------------------------------------------------------" 197 | @echo "TOP = ${TOP}" 198 | @echo "BUILD_DIR = $(BUILD_DIR) (ROOT_DIR=${ROOT_DIR})" 199 | @echo "TARGET = ${BOARD} (DEVICE_CORE=${DEVICE_CORE})" 200 | @echo "DEVICE = ${DEVICE} (STM32=${STM32} CORE=${CORE})" 201 | @echo "APP_DEBUG = $(APP_DEBUG) (APP_OPTIM=${APP_OPTIM} V=${V})" 202 | @echo "CFLAGS-CORE = ${CFLAGS-${CORE}}" 203 | @echo "APP_NAME = ${APP_NAME}" 204 | @echo "TOOLS = GCC=${_TOOLS_VER} (MAKE=${MAKE_VERSION})" 205 | @echo "CFLAGS = $(CFLAGS)" 206 | @echo "LDFLAGS = $(LDFLAGS)" 207 | -------------------------------------------------------------------------------- /mk/cortex-m33.mk: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | ifeq ($(strip $(DEVICE_CORE)),cortex-m33) 13 | 14 | # FPU extension - single precision 15 | FPU = fpv5-sp-d16 16 | FPU_ABI = hard 17 | CORE = cortex-m33 18 | 19 | CFLAGS-${CORE} += -mthumb -mcpu=$(CORE) -mfpu=${FPU} 20 | CFLAGS-${CORE} += -mfloat-abi=${FPU_ABI} 21 | 22 | 23 | ifeq ($(strip $(USE_CMSIS_DSP)),y) 24 | 25 | # see CMSIS/DSP/Include/arm_match.h (V1.5.3) 26 | # 27 | # ARM_MATH_ARMV8MML - to include "core_armv8mml.h" 28 | # __FPU_PRESENT - FPU supported 29 | # __DSP_PRESENT - Armv8-M Mainline core supports DSP instructions 30 | 31 | CFLAGS-${CORE}-CMSIS += -DARM_MATH_ARMV8MML 32 | CFLAGS-${CORE}-CMSIS += -D__DSP_PRESENT=1 33 | CFLAGS-${CORE}-CMSIS += -D__FPU_PRESENT=1U 34 | 35 | CFLAGS-${CORE} += -DARM_MATH_DSP 36 | CFLAGS-${CORE} += -DARM_MATH_LOOPUNROLL 37 | 38 | endif 39 | 40 | LDFLAGS-$(CORE) += -mcpu=${CORE} -mthumb -mfpu=${FPU} -mfloat-abi=${FPU_ABI} 41 | endif 42 | -------------------------------------------------------------------------------- /mk/cortex-m4.mk: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | ifeq ($(strip $(DEVICE_CORE)),cortex-m4) 13 | 14 | FPU = fpv4-sp-d16 15 | FPU_ABI = hard 16 | CORE = cortex-m4 17 | 18 | CFLAGS-${CORE} += -mthumb -mcpu=$(CORE) -mfpu=${FPU} 19 | CFLAGS-${CORE} += -mfloat-abi=${FPU_ABI} 20 | 21 | ifeq ($(strip $(USE_CMSIS_DSP)),y) 22 | 23 | ifeq (${STM32},STM32L4xx) 24 | CFLAGS-${CORE} += -D__FPU_PRESENT=1 25 | else 26 | CFLAGS-${CORE} += -D__FPU_PRESENT=1U 27 | endif 28 | 29 | CFLAGS-${CORE} += -DARM_MATH_CM4 30 | CFLAGS-${CORE} += -DARM_MATH 31 | CFLAGS-${CORE} += -DARM_MATH_DSP 32 | CFLAGS-${CORE} += -DARM_MATH_LOOPUNROLL 33 | endif 34 | 35 | LDFLAGS-$(CORE) += -mcpu=${CORE} -mthumb -mfpu=${FPU} -mfloat-abi=${FPU_ABI} 36 | endif 37 | -------------------------------------------------------------------------------- /mk/cortex-m7-fpdp.mk: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | # 13 | # Target-specific options 14 | # 15 | 16 | ifeq ($(strip $(DEVICE_CORE)),cortex-m7-fpdp) 17 | 18 | FPU = fpv5-d16 19 | FPU_ABI = hard 20 | CORE = cortex-m7 21 | 22 | CFLAGS-${CORE} += -mthumb -mcpu=$(CORE) -mfpu=${FPU} 23 | CFLAGS-${CORE} += -mfloat-abi=${FPU_ABI} 24 | 25 | ifeq ($(strip $(USE_CMSIS_DSP)),y) 26 | CFLAGS-${CORE} += -DARM_MATH_CM7 27 | CFLAGS-${CORE} += -DARM_MATH 28 | CFLAGS-${CORE} += -D__FPU_PRESENT=1 29 | CFLAGS-${CORE} += -DARM_MATH_DSP 30 | CFLAGS-${CORE} += -DARM_MATH_LOOPUNROLL 31 | endif 32 | 33 | LDFLAGS-$(CORE) += -mcpu=$(CORE) -mthumb -mfpu=${FPU} -mfloat-abi=${FPU_ABI} 34 | endif 35 | -------------------------------------------------------------------------------- /mk/cortex-m7.mk: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | ifeq ($(strip $(DEVICE_CORE)),cortex-m7) 13 | 14 | FPU = fpv5-sp-d16 15 | FPU_ABI = hard 16 | CORE = cortex-m7 17 | 18 | CFLAGS-${CORE} += -mthumb -mcpu=$(CORE) -mfpu=${FPU} 19 | CFLAGS-${CORE} += -mfloat-abi=${FPU_ABI} 20 | 21 | ifeq ($(strip $(USE_CMSIS_DSP)),y) 22 | 23 | CFLAGS-${CORE} += -DARM_MATH_CM7 24 | CFLAGS-${CORE} += -DARM_MATH 25 | CFLAGS-${CORE} += -D__FPU_PRESENT=1 26 | 27 | CFLAGS-${CORE} += -DARM_MATH_DSP 28 | CFLAGS-${CORE} += -DARM_MATH_LOOPUNROLL 29 | endif 30 | 31 | LDFLAGS-$(CORE) += -mcpu=${CORE} -mthumb -mfpu=${FPU} -mfloat-abi=${FPU_ABI} 32 | endif 33 | -------------------------------------------------------------------------------- /mk/default.mk: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | # 13 | # Default options 14 | # 15 | 16 | # Indicates how to build the AI lib (see ../Nucleo-Lib/GCC/Makefile) 17 | # 18 | # AI_DEBUG,AI_RELEASE 19 | # ------------------------------------------------- 20 | # 1, x -g3 -O0 -DDEBUG 21 | # 0, 0 -g3 -O3 -DNDEBUG 22 | # 0, 1 -O3 -DNDEBUG -DRELEASE 23 | AI_DEBUG ?= 0 24 | AI_RELEASE ?= 0 25 | 26 | APP_OPTIM ?= -O3 27 | APP_DEBUG ?= 0 28 | 29 | -------------------------------------------------------------------------------- /mk/gcc.mk: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | # 13 | # GCC config 14 | # 15 | 16 | ifeq ($(OS),Windows_NT) 17 | # SHELL := cmd 18 | tmp := 19 | SEP := \$(tmp) 20 | RM := del /f /q 21 | RMDIR := rd /s /q 22 | MKDIR := mkdir 23 | FixPath = $(subst /,\, s$1) 24 | else 25 | SEP := / 26 | RM := rm -f 27 | RMDIR := rm -rf 28 | MKDIR := mkdir -p 29 | FixPath = $1 30 | endif 31 | 32 | CROSS_COMPILE ?= arm-none-eabi- 33 | 34 | ifneq ($(GCC_BIN_DIR),) 35 | _GCC_PREFIX := $(GCC_BIN_DIR)/ 36 | else 37 | _GCC_PREFIX := ${ARM_PATH}/ 38 | endif 39 | 40 | CC = $(_GCC_PREFIX)$(CROSS_COMPILE)gcc 41 | CPP = $(_GCC_PREFIX)$(CROSS_COMPILE)cpp 42 | LD = $(_GCC_PREFIX)$(CROSS_COMPILE)ld 43 | AR = $(_GCC_PREFIX)$(CROSS_COMPILE)ar 44 | NM = $(_GCC_PREFIX)$(CROSS_COMPILE)nm 45 | OBJCOPY = $(_GCC_PREFIX)$(CROSS_COMPILE)objcopy 46 | OBJDUMP = $(_GCC_PREFIX)$(CROSS_COMPILE)objdump 47 | READELF = $(_GCC_PREFIX)$(CROSS_COMPILE)readelf 48 | SIZE = $(_GCC_PREFIX)$(CROSS_COMPILE)size 49 | CXX = $(_GCC_PREFIX)$(CROSS_COMPILE)g++ 50 | 51 | 52 | _TOOLS_VER = $(shell $(CC) -dumpversion) 53 | _TOOLS_DIR = $(shell $(CC) -print-sysroot) 54 | 55 | 56 | -------------------------------------------------------------------------------- /mk/macros.mk: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | # 13 | # Common options 14 | # 15 | 16 | ifneq ($V,1) 17 | q := @ 18 | else 19 | q := 20 | endif 21 | 22 | 23 | define set_cm 24 | sm := $1 25 | $1_cflags := $2 26 | $1_remove_cflags := $3 27 | endef 28 | 29 | # Macro to set the rules to build a specific C file 30 | #------------------------------------------------------------------------------- 31 | # Arguments are: 32 | # 1 - C source file 33 | # 2 - Destination file without extension (generated object) 34 | # 35 | # Global definitions: 36 | # sm - group name, ${sm}_remove_cflags, ${sm}_cflags 37 | # CFLAGS - Pre and compiler options 38 | define process_c_srcs 39 | 40 | #(info Rule for $(1) $(2).o) 41 | objs += $(2).o 42 | 43 | $(eval _base_ := $(notdir $(2))) 44 | $(eval comp-dep-$(_base_) := $(2).d) 45 | $(eval comp-i-$(_base_) := $(2).i) 46 | 47 | ifeq (${${sm}_remove_cflags},) 48 | ${sm}_remove_cflags := 49 | endif 50 | 51 | comp-cflags-$(_base_) := $(CFLAGS) $${cflags-${_base_}.c} 52 | comp-cflags-$(_base_) := $$(filter-out $${${sm}_remove_cflags}, $${comp-cflags-$(_base_)}) 53 | comp-cflags-$(_base_) += $(${sm}_cflags) 54 | 55 | comp-iflags-$(_base_) := $$(comp-cflags-$(_base_)) 56 | comp-cflags-$(_base_) += -MD -MF $$(comp-dep-$(_base_)) -MT $(2).o 57 | 58 | clean-files += $(2).o # $$(comp-dep-$(_base_)) $(2).su $$(comp-i-$(_base_)) 59 | clean-files-dep += $$(comp-dep-$(_base_)) 60 | clean-files-su += $(2).su 61 | clean-files-i += $$(comp-i-$(_base_)) 62 | 63 | -include $$(comp-dep-$(_base_)) 64 | 65 | $(2).o: $(1) 66 | @echo "CC(${sm}) $$<" 67 | @mkdir -p $$(@D) 68 | $(q)$(CC) $$(comp-iflags-$(_base_)) -E $$< -o $$(comp-i-$(_base_)) 69 | $(q)$(CC) $$(comp-cflags-$(_base_)) -c $$< -o $$@ 70 | endef 71 | 72 | # Macro to set the rules to build a specific S file 73 | #------------------------------------------------------------------------------- 74 | # Arguments are: 75 | # 1 - S source file 76 | # 2 - Destination file without extension (generated object) 77 | # 78 | # Global definitions: 79 | # sm - group name 80 | # ASFLAGS - Pre and compiler options 81 | define process_s_srcs 82 | 83 | #(info Rule for $(1) $(2)) 84 | objs += $(2).o 85 | 86 | $(eval _base_ := $(notdir $(2))) 87 | $(eval comp-dep-$(_base_) := $(2).d) 88 | $(eval comp-i-$(_base_) := $(2).i) 89 | 90 | comp-asflags-$(_base_) := $(ASFLAGS) 91 | 92 | clean-files += $(2).o 93 | 94 | -include $$(comp-dep-$(_base_)) 95 | 96 | $(2).o: $(1) 97 | @echo "AS(${sm}) $$<" 98 | @mkdir -p $$(@D) 99 | $(q)$(CC) $$(comp-asflags-$(_base_)) -c $$< -o $$@ 100 | endef 101 | 102 | 103 | # Macro to set the rules to build a specific CC file 104 | #------------------------------------------------------------------------------- 105 | # Arguments are: 106 | # 1 - C++ source file 107 | # 2 - Destination file without extension (generated object) 108 | # 109 | # Global definitions: 110 | # sm - group name, ${sm}_remove_cxxflags, ${sm}_cxxflags 111 | # CXXFLAG - Pre and compiler options 112 | define process_cc_srcs 113 | 114 | #(info Rule for $(1) $(2)) 115 | objs += $(2).o 116 | 117 | $(eval _base_ := $(notdir $(2))) 118 | $(eval comp-dep-$(_base_) := $(2).d) 119 | $(eval comp-i-$(_base_) := $(2).i) 120 | 121 | ifeq (${${sm}_remove_cxxflags},) 122 | ${sm}_remove_cxxflags := 123 | endif 124 | 125 | comp-cxxflags-$(_base_) := $(CXXFLAGS) $${cxxflags-${_base_}.cc} 126 | comp-cxxflags-$(_base_) := $$(filter-out $${${sm}_remove_cxxflags}, $${comp-cxxflags-$(_base_)}) 127 | comp-cxxflags-$(_base_) += $(${sm}_cxxflags) 128 | 129 | comp-ixxflags-$(_base_) := $$(comp-cxxflags-$(_base_)) 130 | comp-cxxflags-$(_base_) += -MD -MF $$(comp-dep-$(_base_)) -MT $(2).o 131 | 132 | clean-files += $(2).o # $$(comp-dep-$(_base_)) $(2).su $$(comp-i-$(_base_)) 133 | clean-files-dep += $$(comp-dep-$(_base_)) 134 | clean-files-su += $(2).su 135 | clean-files-i += $$(comp-i-$(_base_)) 136 | 137 | -include $$(comp-dep-$(_base_)) 138 | 139 | $(2).o: $(1) 140 | @echo "CXX(${sm}) $$<" 141 | @mkdir -p $$(@D) 142 | $(q)$(CXX) $$(comp-ixxflags-$(_base_)) -E $$< -o $$(comp-i-$(_base_)) 143 | $(q)$(CXX) $$(comp-cxxflags-$(_base_)) -c $$< -o $$@ 144 | endef 145 | -------------------------------------------------------------------------------- /scripts/ai_runner/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | """Module container of STM32 code generator.""" 13 | 14 | from .ai_runner import AiRunner 15 | from .ai_runner import AiRunnerCallback 16 | from .ai_runner import AiRunnerSession 17 | -------------------------------------------------------------------------------- /scripts/ai_runner/ai_resolver.py: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | """ 13 | Entry point to register a driver 14 | 15 | Expected syntax for driver description/options for the connection 16 | 17 | [[:[:option2]]] 18 | 19 | domain: 20 | - None or 'serial' (default) 21 | - 'dll' or valid file_path/directory 22 | - 'socket' 23 | 24 | """ 25 | 26 | import os 27 | 28 | _DEFAULT_DOMAIN = "serial" 29 | _FILE_DOMAIN = "file" 30 | 31 | 32 | def _default_resolver(domain, desc=None): # pylint: disable=unused-argument 33 | """Default resolver function""" 34 | # if domain == _DEFAULT_DOMAIN or domain == None: 35 | if domain in (_DEFAULT_DOMAIN, None): 36 | return True 37 | return False 38 | 39 | 40 | def _default_create(parent, desc): 41 | """Default create function""" 42 | from .serial_hw_drv import SerialHwDriver # pylint: disable=import-outside-toplevel 43 | from .pb_mgr_drv import AiPbMsg # pylint: disable=import-outside-toplevel 44 | 45 | return AiPbMsg(parent, SerialHwDriver()), desc 46 | 47 | 48 | _DRIVERS = { 49 | _DEFAULT_DOMAIN: (_default_resolver, _default_create), # default 50 | } 51 | 52 | 53 | def ai_runner_register(name, resolver, create): 54 | """Register a resolver""" 55 | _DRIVERS[name] = (resolver, create) 56 | 57 | 58 | def ai_runner_resolver(parent, desc): 59 | """Return drv instance""" 60 | 61 | if desc is not None and isinstance(desc, str): 62 | desc = desc.strip() 63 | split_ = desc.split(":") 64 | nb_elem = len(split_) 65 | 66 | domain = None 67 | # only valid file or directory is passed 68 | if os.path.isfile(desc) or os.path.isdir(desc) or os.path.isdir(os.path.dirname(desc)): 69 | domain = _FILE_DOMAIN 70 | # domain is considered 71 | elif nb_elem >= 1 and len(split_[0]) > 0: 72 | domain = split_[0].lower() 73 | desc = desc[len(domain + ":") :] 74 | # ':' is passed as first character 75 | elif len(split_[0]) == 0: 76 | domain = _DEFAULT_DOMAIN 77 | desc = desc[1:] 78 | 79 | for drv_ in _DRIVERS: 80 | if _DRIVERS[drv_][0](domain, desc): 81 | return _DRIVERS[drv_][1](parent, desc) 82 | 83 | err_msg_ = f'invalid/unsupported "{domain}:{desc}" descriptor' 84 | return None, err_msg_ 85 | 86 | # else: 87 | return _DRIVERS[_DEFAULT_DOMAIN][1](parent, desc) 88 | -------------------------------------------------------------------------------- /scripts/ai_runner/requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | numpy 13 | protobuf 14 | pyserial==3.4 15 | tqdm==4.50.2 16 | 17 | -------------------------------------------------------------------------------- /scripts/ai_runner/serial_hw_drv.py: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | # pylint: disable=invalid-name 13 | 14 | """ 15 | Serial Low Level or Hw Driver 16 | """ 17 | 18 | import time as t 19 | 20 | from serial import Serial 21 | import serial.tools.list_ports 22 | from serial.serialutil import SerialException 23 | 24 | from .ai_runner import AiHwDriver 25 | from .ai_runner import HwIOError 26 | 27 | 28 | def serial_device_discovery(): 29 | """Scan for available serial ports. return a list of available ports""" 30 | 31 | comports = serial.tools.list_ports.comports() 32 | dev_list = [] 33 | for com in comports: 34 | elem = { 35 | "type": "serial", 36 | "device": com.device, 37 | "desc": com.description, 38 | "hwid": com.hwid, 39 | } 40 | dev_list.append(elem) 41 | 42 | return dev_list 43 | 44 | 45 | def serial_get_com_settings(desc): 46 | """ 47 | Parse the desc parameter to retreive the COM id and the baudrate. 48 | Can be a "str" or directly an "int" if only the baudrate is passed. 49 | 50 | Example: 51 | 52 | 'COM7:115200' -> 'COM7' 115200 53 | '460800' -> None 460800 54 | ':921600 -> None 921600 55 | 'COM6' -> COM6 115200 56 | ':COM6 -> COM6 115200 57 | 58 | """ 59 | 60 | # default values 61 | port_ = None 62 | baud_ = int(115200) 63 | 64 | if desc is not None and isinstance(desc, int): 65 | return port_, int(desc) 66 | 67 | if desc is None or not isinstance(desc, str): 68 | return port_, baud_ 69 | 70 | desc = desc.split(":") 71 | for _d in desc: 72 | if _d: 73 | try: 74 | _d = int(_d) 75 | except (ValueError, TypeError): 76 | port_ = _d 77 | else: 78 | baud_ = _d 79 | 80 | return port_, baud_ 81 | 82 | 83 | class SerialHwDriver(AiHwDriver): 84 | """Serial low-level IO driver""" 85 | 86 | def __init__(self, parent=None): 87 | """Constructor""" 88 | self._device = None 89 | self._baudrate = 0 90 | super().__init__(parent) 91 | 92 | def get_config(self): 93 | """"Return a dict with used configuration""" 94 | return { 95 | "device": self._device, 96 | "baudrate": self._baudrate, 97 | } 98 | 99 | def _open(self, device, baudrate, timeout, dry_run=False): 100 | """Open the COM port""" 101 | _RETRY = 4 102 | hdl = None 103 | while _RETRY: 104 | try: 105 | hdl = Serial(device, baudrate=baudrate, timeout=timeout) 106 | except SerialException as _e: 107 | _RETRY -= 1 108 | if not _RETRY: 109 | if not dry_run: 110 | raise HwIOError("{}".format(_e)) 111 | # else: 112 | return None 113 | t.sleep(0.2) 114 | else: 115 | break 116 | return hdl 117 | 118 | def _discovery(self, device, baudrate, timeout): 119 | """Discover the possible COM port""" 120 | if device is None: 121 | devices = serial_device_discovery() 122 | else: 123 | devices = [{"device": device}] 124 | for dev in devices: 125 | dry_run = dev != devices[-1] 126 | hdl_ = self._open(dev["device"], baudrate, timeout, dry_run=dry_run) 127 | if hdl_: 128 | self._hdl = hdl_ 129 | self._hdl.reset_input_buffer() 130 | self._hdl.reset_output_buffer() 131 | self._device = dev["device"] 132 | self._baudrate = baudrate 133 | cpt = 1000 134 | while self._read(10) and cpt: 135 | cpt = cpt - 1 136 | t.sleep(0.4) 137 | if hasattr(self._parent, "is_alive") and self._parent.is_alive(): 138 | return 139 | self._hdl.close() 140 | self._hdl = None 141 | if not dry_run: 142 | raise HwIOError( 143 | "{} - {}:{}".format("Invalid firmware", dev["device"], baudrate) 144 | ) 145 | # return None 146 | 147 | def _connect(self, desc=None, **kwargs): 148 | """Open a connection""" 149 | 150 | dev_, baud_ = serial_get_com_settings(desc) 151 | baud_ = kwargs.get("baudrate", baud_) 152 | timeout_ = kwargs.get("timeout", 0.001) 153 | 154 | self._discovery(dev_, baud_, timeout_) 155 | 156 | return self.is_connected 157 | 158 | def _disconnect(self): 159 | """Close the connection""" 160 | self._hdl.reset_input_buffer() 161 | self._hdl.reset_output_buffer() 162 | self._hdl.close() 163 | self._hdl = None 164 | 165 | def _read(self, size, timeout=0): 166 | """Read data from the connected device""" 167 | return self._hdl.read(size) 168 | 169 | def _write(self, data, timeout=0): 170 | """Write data to the connected device""" 171 | return self._hdl.write(data) 172 | 173 | def short_desc(self): 174 | """Report a human description of the connection state""" 175 | desc = "SERIAL:" + str(self._device) + ":" + str(self._baudrate) 176 | desc += ":connected" if self.is_connected else ":not connected" 177 | return desc 178 | 179 | 180 | if __name__ == "__main__": 181 | pass 182 | -------------------------------------------------------------------------------- /scripts/ai_runner/stm32_utility.py: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | """ 13 | STM32 helper functions 14 | """ 15 | 16 | # todo - push the STM32 flags/definition in an interface file (TBD) to share them 17 | # with the C-code. 18 | 19 | # format(32b) 31..24: STM32 series 20 | # 23..17: spare 21 | # 16: FPU is enabled or not 22 | # 15..12: spare 23 | # 11: H7/F7:D$ is enabled 24 | # 10: H7/F7:I$ is enabled F4/L4: ART DCen 25 | # 9: F7: ART enabled F4/L4: ART ICen L5: ICACHE 26 | # 8: F4/L4/F7:ART Prefetch enabled 27 | # 7..0: ART number of cycles (latency) 28 | # 29 | 30 | _STM32_SERIES_F4 = 1 31 | _STM32_SERIES_F7 = 2 32 | _STM32_SERIES_H7 = 3 33 | _STM32_SERIES_L5 = 4 34 | _STM32_SERIES_L4 = 1 35 | 36 | 37 | def _is_series(fmt, series): 38 | return (fmt >> 24) == series 39 | 40 | 41 | def stm32_id_to_str(dev_id): 42 | """Helper function to return a Human readable device ID description""" 43 | 44 | switcher = { 45 | 0x422: "STM32F303xB/C", 46 | 0x438: "STM32F303x6/8", 47 | 0x446: "STM32F303xD/E", 48 | 0x431: "STM32F411xC/E", 49 | 0x423: "STM32F401xB/C", 50 | 0x433: "STM32F401xD/E", 51 | 0x435: "STM32L43xxx", 52 | 0x462: "STM32L45xxx", 53 | 0x415: "STM32L4x6xx", 54 | 0x470: "STM32L4Rxxx", 55 | 0x472: "STM32L5[5,6]2xx", 56 | 0x449: "STM32F74xxx", 57 | 0x450: "STM32H743/53/50xx and STM32H745/55/47/57xx", 58 | 0x451: "STM32F7[6,7]xxx", 59 | } 60 | desc_ = "0x{:X} - ".format(dev_id) 61 | desc_ += switcher.get(dev_id, "UNKNOW") 62 | return desc_ 63 | 64 | 65 | def stm32_config_to_str(cache): 66 | """Return human desc fpu/cache config 67 | see FW c-file aiTestUtility.c 68 | """ 69 | 70 | def _fpu(cache_): 71 | if cache_ & (1 << 16): 72 | return "FPU enabled" 73 | return "no FPU" 74 | 75 | def _lat(cache_): 76 | if (cache_ >> 24) > 0 and not _is_series(cache, _STM32_SERIES_L5): 77 | return "lat={}".format(cache_ & 0xFF) 78 | return "" 79 | 80 | def _art_f4(cache_): 81 | desc = "ART:" 82 | if cache_ & 1 << 8: 83 | desc += " PRFTen" 84 | if cache_ & 1 << 9: 85 | desc += " ICen" 86 | if cache_ & 1 << 10: 87 | desc += " DCen" 88 | return desc 89 | 90 | def _icache_l5(cache_): 91 | desc = "ICACHE: " 92 | desc += "enabled" if cache_ & 1 << 9 else "disabled" 93 | return desc 94 | 95 | def _core_f7h7(cache_): 96 | desc = "Core:" 97 | if cache_ & 1 << 10: 98 | desc += "I$" 99 | else: 100 | desc += "--" 101 | if cache_ & 1 << 11: 102 | desc += "/D$" 103 | else: 104 | desc += "/--" 105 | return desc 106 | 107 | def _art_f7(cache_): 108 | desc = "ART:" 109 | if cache_ & 1 << 8: 110 | desc += " PRFTen" 111 | if cache_ & 1 << 9: 112 | desc += " ARTen" 113 | return desc 114 | 115 | desc = _fpu(cache) 116 | attr = _lat(cache) 117 | desc += ", " + attr if attr else "" 118 | 119 | if _is_series(cache, _STM32_SERIES_F4) or _is_series(cache, _STM32_SERIES_L4): 120 | attr = _art_f4(cache) 121 | desc += ", " + attr if attr else "" 122 | 123 | if _is_series(cache, _STM32_SERIES_F7) or _is_series(cache, _STM32_SERIES_H7): 124 | attr = _core_f7h7(cache) 125 | desc += ", " + attr if attr else "" 126 | 127 | if _is_series(cache, _STM32_SERIES_F7): 128 | attr = _art_f7(cache) 129 | desc += ", " + attr if attr else "" 130 | 131 | if _is_series(cache, _STM32_SERIES_L5): 132 | attr = _icache_l5(cache) 133 | desc += ", " + attr if attr else "" 134 | 135 | return desc 136 | -------------------------------------------------------------------------------- /scripts/ai_runner/stm_ai_utils.py: -------------------------------------------------------------------------------- 1 | # 2 | # @attention 3 | # 4 | # Copyright (c) 2022 STMicroelectronics. 5 | # All rights reserved. 6 | # 7 | # This software is licensed under terms that can be found in the LICENSE file 8 | # in the root directory of this software component. 9 | # If no LICENSE file comes with this software, it is provided AS-IS. 10 | # 11 | 12 | """ 13 | Common helper services to manage the STM.AI type 14 | """ 15 | 16 | 17 | def stm_ai_error_to_str(err_code, err_type): 18 | """Return a human readable description of the ai run-time error 19 | 20 | see ::EmbedNets git (src/api/ai_platform.h file) 21 | """ 22 | 23 | type_switcher = { 24 | 0x00: "None", 25 | 0x01: "Tools Platform Api Mismatch", 26 | 0x02: "Types Mismatch", 27 | 0x10: "Invalid handle", 28 | 0x11: "Invalid State", 29 | 0x12: "Invalid Input", 30 | 0x13: "Invalid Output", 31 | 0x14: "Invalid Param", 32 | 0x30: "Init Failed", 33 | 0x31: "Allocation Failed", 34 | 0x32: "Deallocation Failed", 35 | 0x33: "Create Failed", 36 | } 37 | 38 | code_switcher = { 39 | 0x0000: "None", 40 | 0x0010: "Network", 41 | 0x0011: "Network Params", 42 | 0x0012: "Network Weights", 43 | 0x0013: "Network Activations", 44 | 0x0014: "Layer", 45 | 0x0015: "Tensor", 46 | 0x0016: "Array", 47 | 0x0017: "Invalid Ptr", 48 | 0x0018: "Invalid Size", 49 | 0x0020: "Invalid Format", 50 | 0x0021: "Invalid Batch", 51 | 0x0030: "Missed Init", 52 | 0x0040: "In Use", 53 | } 54 | 55 | desc_ = 'type=0x{:x}("{}")'.format(err_type, type_switcher.get(err_type, str(err_type))) 56 | desc_ += '/code=0x{:x}("{}")'.format(err_code, code_switcher.get(err_code, str(err_code))) 57 | 58 | return desc_ 59 | 60 | 61 | def stm_ai_node_type_to_str(n_type, full=True): 62 | """Return a human readable description of a CNode / Clayer 63 | 64 | see ::EmbedNets git (src/layers/layers_list.h file) 65 | """ 66 | base = 0x100 # stateless operator 67 | base_2 = 0x180 # stateful operator 68 | n_type = n_type & 0xFFFF 69 | ls_switcher = { 70 | 0: "Output", 71 | base: "Base", 72 | base + 1: "Add", 73 | base + 2: "BN", 74 | base + 3: "Conv2D", 75 | base + 4: "Dense", 76 | base + 5: "GRU", 77 | base + 6: "LRN", 78 | base + 7: "NL", 79 | base + 8: "Norm", 80 | base + 9: "Conv2dPool", 81 | base + 10: "Transpose", 82 | base + 11: "Pool", 83 | base + 12: "Softmax", 84 | base + 13: "Split", 85 | base + 14: "TimeDelay", 86 | base + 15: "TimeDistributed", 87 | base + 16: "Concat", 88 | base + 17: "GEMM", 89 | base + 18: "Upsample", 90 | base + 19: "Eltwise", 91 | base + 20: "EltwiseInt", 92 | base + 21: "InstNorm", 93 | base + 22: "Pad", 94 | base + 23: "Slice", 95 | base + 24: "Tile", 96 | base + 25: "Reduce", 97 | base + 26: "RNN", 98 | base + 27: "Resize", 99 | base + 28: "Gather", 100 | base + 29: "Pack", 101 | base + 30: "UnPack", 102 | base + 31: "Container", 103 | base + 32: "Lambda", 104 | base_2: "Stateful", 105 | base_2 + 1: "LSTM", 106 | base_2 + 2: "Custom", 107 | } 108 | desc_ = "{}".format(ls_switcher.get(n_type, str(n_type))) 109 | if full: 110 | desc_ += " (0x{:x})".format(n_type) 111 | return desc_ 112 | -------------------------------------------------------------------------------- /scripts/compile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | # @attention 5 | # 6 | # Copyright (c) 2022 STMicroelectronics. 7 | # All rights reserved. 8 | # 9 | # This software is licensed under terms that can be found in the LICENSE file 10 | # in the root directory of this software component. 11 | # If no LICENSE file comes with this software, it is provided AS-IS. 12 | # 13 | 14 | """Compile TFLite model for the STM32 target.""" 15 | 16 | import os 17 | import shutil 18 | import sys 19 | import argparse 20 | import tarfile 21 | 22 | # 23 | # Disable GPU usage information: 24 | # 25 | # 26 | # 0 = all messages are logged (default behavior) 27 | # 1 = INFO messages are not printed 28 | # 2 = INFO and WARNING messages are not printed 29 | # 3 = INFO, WARNING, and ERROR messages are not printed 30 | os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2" 31 | 32 | import numpy as np 33 | 34 | import re 35 | 36 | import tensorflow as tf 37 | 38 | import tvm 39 | import tvm.relay as relay 40 | from tvm.micro.contrib import stm32 41 | 42 | import logging 43 | 44 | # ======================================================== 45 | # get_tflite_model 46 | # ======================================================== 47 | def get_tflite_model(model_path): 48 | 49 | # 50 | # Load TFLite model and allocate tensors. 51 | # 52 | interpreter = tf.lite.Interpreter(model_path=model_path) 53 | interpreter.allocate_tensors() 54 | # 55 | # Get input and output tensors. 56 | # 57 | input_details = interpreter.get_input_details() 58 | output_details = interpreter.get_output_details() 59 | 60 | # 61 | # Figure out shapes and 62 | # 63 | 64 | shape_dict = {} 65 | dtype_dict = {} 66 | 67 | for input in input_details: 68 | input_name = input["name"] 69 | input_shape = input["shape"].tolist() 70 | input_dtype = str(np.dtype(input["dtype"])) 71 | shape_dict[input_name] = input_shape 72 | dtype_dict[input_name] = input_dtype 73 | 74 | # 75 | # Load the TFLite Model for TVM: 76 | # 77 | # https://docs.tvm.ai/tutorials/frontend/from_tflite.html 78 | # https://jackwish.net/tflite/docs/ 79 | 80 | model_buf = open(model_path, "rb").read() 81 | 82 | # 83 | # Get TFLite model from buffer 84 | # 85 | try: 86 | import tflite 87 | 88 | model = tflite.Model.GetRootAsModel(model_buf, 0) 89 | assert isinstance(model, tflite.Model) 90 | except AttributeError: 91 | import tflite.Model 92 | 93 | model = tflite.Model.Model.GetRootAsModel(model_buf, 0) 94 | assert isinstance(model, tflite.Model.Model) 95 | 96 | print("TVM: Importing a TFLite model ...") 97 | 98 | return model, shape_dict, dtype_dict 99 | 100 | 101 | # ======================================================== 102 | # extract_tflite_quantization 103 | # ======================================================== 104 | 105 | 106 | def _make_qnn_params(quantization): 107 | qnn_params = {} 108 | qnn_params["min"] = quantization.MinAsNumpy() 109 | qnn_params["max"] = quantization.MaxAsNumpy() 110 | qnn_params["scale"] = quantization.ScaleAsNumpy() 111 | qnn_params["zero_point"] = quantization.ZeroPointAsNumpy() 112 | qnn_params["dim"] = quantization.QuantizedDimension() 113 | # print(" Quantization: ({}, {}), s={}, z={}, dim={}".format(min, max, scale, zero_point, dim)) 114 | return qnn_params 115 | 116 | 117 | def extract_tflite_quantization(model): 118 | 119 | assert model.SubgraphsLength() == 1, "only support one subgraph (main subgraph)" 120 | 121 | subgraph = model.Subgraphs(0) 122 | 123 | quantization_info = {} 124 | 125 | # model inputs / outputs 126 | model_inputs = subgraph.InputsAsNumpy() 127 | model_outputs = subgraph.OutputsAsNumpy() 128 | 129 | for node_id in model_inputs: 130 | tensor = subgraph.Tensors(node_id) 131 | tensor_name = tensor.Name().decode("utf-8") 132 | tensor_type = tensor.Type() 133 | # print("== Input[{}]: {} shape={} type={}".format(node_id, tensor_name, tensor.ShapeAsNumpy(), tensor_type)) 134 | dl_tensor_name = stm32.get_input_tensor_name(tensor_name) 135 | 136 | quantization = tensor.Quantization() 137 | if quantization is not None: 138 | qnn_params = _make_qnn_params(quantization) 139 | quantization_info[dl_tensor_name] = qnn_params 140 | 141 | for node_id in model_outputs: 142 | tensor = subgraph.Tensors(node_id) 143 | tensor_name = tensor.Name().decode("utf-8") 144 | tensor_type = tensor.Type() 145 | # print("== Output[{}]: {} shape={} type={}".format(node_id, tensor_name, tensor.ShapeAsNumpy(), tensor_type)) 146 | # 147 | # TODO: TVM does not preserve the output tensor names. 148 | # Eventually, we should be able to form a valid name. 149 | # 150 | dl_tensor_name = stm32.get_output_tensor_name(tensor_name, 0) 151 | 152 | quantization = tensor.Quantization() 153 | if quantization is not None: 154 | qnn_params = _make_qnn_params(quantization) 155 | quantization_info[dl_tensor_name] = qnn_params 156 | 157 | return quantization_info 158 | 159 | 160 | # ================================================================== 161 | # __main__ 162 | # ================================================================== 163 | if __name__ == "__main__": 164 | 165 | curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__))) 166 | 167 | parser = argparse.ArgumentParser() 168 | 169 | parser.add_argument("-model", type=str, required=True, help="The TFLite model to compile") 170 | parser.add_argument("-name", type=str, help="The name for the generated implementation") 171 | parser.add_argument( 172 | "-target-dir", type=str, help="The directory for storing the generated implementation" 173 | ) 174 | 175 | args = parser.parse_args() 176 | 177 | model_path = args.model 178 | target_dir = args.target_dir 179 | 180 | # 181 | # Extract the model name 182 | # 183 | model_file = os.path.basename(model_path) 184 | print("=== TVM: Model name: {}".format(model_file)) 185 | model_file_ext = os.path.splitext(model_file) 186 | assert model_file_ext[1] == ".tflite" 187 | 188 | if not args.name: 189 | model_name = model_file_ext[0] 190 | else: 191 | model_name = args.name 192 | 193 | if not target_dir: 194 | target_dir = model_file_ext[0] + "_gen" 195 | 196 | if os.path.exists(target_dir): 197 | print(f'Removing existing "{target_dir}" directory') 198 | try: 199 | shutil.rmtree(target_dir) 200 | except OSError as err: 201 | raise ValueError(f"emit_code.Error: {target_dir} : {err.strerror}") 202 | 203 | # Make a new one 204 | os.makedirs(target_dir) 205 | 206 | model, shape_dict, dtype_dict = get_tflite_model(model_path) 207 | 208 | # 209 | # Import the model with relay 210 | # 211 | 212 | print("=== TVM: Importing the model.") 213 | 214 | mod, params = relay.frontend.from_tflite(model, shape_dict, dtype_dict) 215 | 216 | print("=== TVM: Compiling the TFLite model ...") 217 | 218 | # 219 | # Build a TVM C module for the ARM CPU (without compiling the kernels 220 | # library to the object code form): 221 | # 222 | target = "c -device=arm_cpu" 223 | opt_level = 3 224 | 225 | with tvm.transform.PassContext(opt_level=opt_level, config={"tir.disable_vectorize": True}): 226 | rt_module = relay.build(mod, target=target, params=params) 227 | # 228 | # Export model library format 229 | # 230 | mlf_tar_path = os.path.join(target_dir, model_name + "_lib.tar") 231 | import tvm.micro as micro 232 | 233 | micro.export_model_library_format(rt_module, mlf_tar_path) 234 | 235 | # 236 | # Instantiate the STM32 code emitter. 237 | # May take 3 optional arguments: 238 | # - include_activations : activations area is statically allocated with *.nn_data_act section (default: True) 239 | # - include_inputs : input area is statically allocated with *.nn_data_act section sharing memory with activation buffers (default: True) 240 | # - include_outputs : output area is statically allocated with *.nn_data_act section sharing memory with activation buffers (default: True) 241 | # 242 | emitter = stm32.CodeEmitter() 243 | # 244 | # Extract model's inputs/outputs quantization info. 245 | # NOTE: TVM does not provide this -- workaround. 246 | # Prepare the quantization info if network is quantized 247 | # builds a dictionary of the form: 248 | # 249 | # { 250 | # "tensor-name>": {'min':fp, 'max':fp, 'scale':fp, 'zero_point':int, 'dim':int} 251 | # "tensor-name>": {'min':fp, 'max':fp, 'scale':fp, 'zero_point':int, 'dim':int} 252 | # ... 253 | # "tensor-name>": {'min':fp, 'max':fp, 'scale':fp, 'zero_point':int, 'dim':int} 254 | # } 255 | # 256 | quantization = extract_tflite_quantization(model) 257 | 258 | print("== Quantization: {}".format(quantization)) 259 | 260 | # 261 | # Initialize the emiiter: use the LibraryModuleFormat 262 | # 263 | # emitter.parse_model (rt_module, quantization) 264 | emitter.parse_library_format(mlf_tar_path, quantization) 265 | 266 | # 267 | # Emit the C code 268 | # 269 | emitter.emit_code(target_dir, model_name) 270 | 271 | print("=== TVM: TFLite model compiled.") 272 | -------------------------------------------------------------------------------- /scripts/minimal.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | # @attention 5 | # 6 | # Copyright (c) 2022 STMicroelectronics. 7 | # All rights reserved. 8 | # 9 | # This software is licensed under terms that can be found in the LICENSE file 10 | # in the root directory of this software component. 11 | # If no LICENSE file comes with this software, it is provided AS-IS. 12 | # 13 | 14 | """ 15 | Minimal example - Invoke a model with the random data 16 | """ 17 | 18 | import sys 19 | import argparse 20 | from statistics import mean 21 | from ai_runner import AiRunner 22 | 23 | _DEFAULT = "serial" 24 | 25 | 26 | def example(args): 27 | 28 | runner = AiRunner(debug=args.debug) 29 | 30 | if not runner.connect(args.desc): 31 | return 1 32 | 33 | print(runner, flush=True) 34 | 35 | runner.summary(level=args.verbosity) 36 | 37 | inputs = runner.generate_rnd_inputs(batch_size=args.batch) 38 | 39 | print("Invoking the model with random data (b={})..".format(inputs[0].shape[0]), flush=True) 40 | _, profile = runner.invoke(inputs) 41 | 42 | print("") 43 | print("host execution time : {:.3f}ms".format(profile["debug"]["host_duration"])) 44 | print("number of samples : {}".format(len(profile["c_durations"]))) 45 | print("inference time by sample : {:.3f}ms (average)".format(mean(profile["c_durations"]))) 46 | print("") 47 | 48 | runner.disconnect() 49 | 50 | return 0 51 | 52 | 53 | def main(): 54 | """ script entry point """ 55 | 56 | parser = argparse.ArgumentParser(description="Minimal example") 57 | 58 | parser.add_argument( 59 | "--desc", 60 | "-d", 61 | metavar="STR", 62 | type=str, 63 | help="description for the connection", 64 | default=_DEFAULT, 65 | ) 66 | parser.add_argument( 67 | "--batch", "-b", metavar="INT", type=int, help="number of sample", default=1 68 | ) 69 | parser.add_argument("--debug", action="store_true", help="debug option") 70 | parser.add_argument( 71 | "--verbosity", 72 | "-v", 73 | nargs="?", 74 | const=1, 75 | type=int, 76 | choices=range(0, 3), 77 | help="set verbosity level", 78 | default=0, 79 | ) 80 | 81 | args = parser.parse_args() 82 | 83 | return example(args) 84 | 85 | 86 | if __name__ == "__main__": 87 | sys.exit(main()) 88 | -------------------------------------------------------------------------------- /scripts/mnist_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | # @attention 5 | # 6 | # Copyright (c) 2022 STMicroelectronics. 7 | # All rights reserved. 8 | # 9 | # This software is licensed under terms that can be found in the LICENSE file 10 | # in the root directory of this software component. 11 | # If no LICENSE file comes with this software, it is provided AS-IS. 12 | # 13 | 14 | """ 15 | Typical script to the test dataset and specific metric 16 | (i.e. sklearn classification metric) to evaluate the generated model 17 | with the MNIST data set. 18 | """ 19 | 20 | import os 21 | import argparse 22 | from statistics import mean 23 | import logging 24 | import numpy as np 25 | 26 | from sklearn.metrics import classification_report 27 | 28 | os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3" 29 | logging.getLogger("tensorflow").setLevel(logging.ERROR) 30 | 31 | from tensorflow import keras 32 | 33 | from ai_runner import AiRunner 34 | 35 | _DEFAULT = "serial" 36 | 37 | 38 | H, W, C = 28, 28, 1 39 | IN_SHAPE = (H, W, C) 40 | NB_CLASSES = 10 41 | 42 | 43 | def load_data_test(): 44 | """Load MNIST data set """ 45 | mnist = keras.datasets.mnist 46 | (_, _), (x_test, y_test) = mnist.load_data() 47 | 48 | # Normalize the input image so that each pixel value is between 0 to 1. 49 | x_test = x_test / 255.0 50 | x_test = x_test.reshape(x_test.shape[0], H, W, C).astype(np.float32) 51 | 52 | # convert class vectors to binary class matrices 53 | y_test = keras.utils.to_categorical(y_test, NB_CLASSES) 54 | 55 | return x_test, y_test 56 | 57 | 58 | parser = argparse.ArgumentParser(description="Test model") 59 | parser.add_argument("--desc", "-d", metavar="STR", type=str, default=_DEFAULT) 60 | parser.add_argument("--batch", "-b", metavar="INT", type=int, default=None) 61 | args = parser.parse_args() 62 | 63 | print('using "{}"'.format(args.desc)) 64 | runner = AiRunner() 65 | 66 | if not runner.connect(args.desc): 67 | print('runtime "{}" is not connected'.format(args.desc)) 68 | exit(1) 69 | 70 | print(runner, flush=True) 71 | runner.summary() 72 | 73 | 74 | # Load the data 75 | inputs, refs = load_data_test() 76 | 77 | if not "machine" in runner.get_info()["device"]: 78 | nb = 100 if not args.batch else args.batch 79 | print( 80 | "INFO: use only the first {} samples (instead {})".format(nb, inputs.shape[0]), flush=True 81 | ) 82 | inputs = inputs[:nb] 83 | refs = refs[:nb] 84 | 85 | # Perform the inference 86 | predictions, profile = runner.invoke(inputs) 87 | 88 | # Display profiling info 89 | print("") 90 | print("execution time : {:.3f}s".format(profile["debug"]["host_duration"] / 1000)) 91 | print("number of samples : {}".format(len(profile["c_durations"]))) 92 | print("inference time by sample : {:.3f}ms (average)".format(mean(profile["c_durations"]))) 93 | 94 | # classification report 95 | print("\nClassification report (sklearn.metrics)\n") 96 | 97 | # align the shape of the outputs (c-model is always - (b, h, w, c)) 98 | predictions[0] = predictions[0].reshape(refs.shape) 99 | 100 | target_names = ["c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9"] 101 | print( 102 | classification_report( 103 | np.argmax(refs, axis=1), np.argmax(predictions[0], axis=1), target_names=target_names 104 | ) 105 | ) 106 | 107 | runner.disconnect() 108 | -------------------------------------------------------------------------------- /scripts/mnist_train.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | # @attention 5 | # 6 | # Copyright (c) 2022 STMicroelectronics. 7 | # All rights reserved. 8 | # 9 | # This software is licensed under terms that can be found in the LICENSE file 10 | # in the root directory of this software component. 11 | # If no LICENSE file comes with this software, it is provided AS-IS. 12 | # 13 | 14 | """ 15 | Typical script to create and train a model with the MNIST dataset. 16 | The trained H5 file is post-quantized with the TFLite converter. 17 | """ 18 | 19 | import os 20 | import logging 21 | 22 | import numpy as np 23 | 24 | os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3" 25 | logging.getLogger("tensorflow").setLevel(logging.ERROR) 26 | 27 | import tensorflow as tf 28 | 29 | from tensorflow import keras 30 | 31 | H, W, C = 28, 28, 1 32 | IN_SHAPE = (H, W, C) 33 | NB_CLASSES = 10 34 | 35 | # Create and train a digit classification model 36 | 37 | 38 | def load_data(): 39 | """Load MNIST data set """ 40 | mnist = tf.keras.datasets.mnist 41 | (x_train, y_train), (x_test, y_test) = mnist.load_data() 42 | 43 | # Normalize the input image so that each pixel value is between 0 to 1. 44 | x_train = x_train / 255.0 45 | x_test = x_test / 255.0 46 | 47 | x_train = x_train.reshape(x_train.shape[0], H, W, C) 48 | x_test = x_test.reshape(x_test.shape[0], H, W, C) 49 | 50 | # convert class vectors to binary class matrices 51 | y_train = keras.utils.to_categorical(y_train, NB_CLASSES) 52 | y_test = keras.utils.to_categorical(y_test, NB_CLASSES) 53 | 54 | return x_train, y_train, x_test, y_test 55 | 56 | 57 | def build_model(): 58 | """Define the model architecture.""" 59 | model = tf.keras.Sequential( 60 | [ 61 | tf.keras.layers.InputLayer(input_shape=IN_SHAPE), 62 | tf.keras.layers.Conv2D(filters=12, kernel_size=(3, 3), activation=tf.nn.relu), 63 | tf.keras.layers.MaxPooling2D(pool_size=(2, 2)), 64 | tf.keras.layers.Dropout(0.5), 65 | tf.keras.layers.Flatten(), 66 | tf.keras.layers.Dense(10, activation="softmax"), 67 | ] 68 | ) 69 | 70 | model.compile( 71 | optimizer="adam", loss=keras.losses.categorical_crossentropy, metrics=["accuracy"] 72 | ) 73 | 74 | model.summary() 75 | 76 | return model 77 | 78 | 79 | def _get_shape_inputs(k_model): 80 | """Return list of input shape""" 81 | # print('Type ', isinstance(k_model, km.Model)) 82 | # layer.output_shape 83 | if k_model.__class__.__name__ == "Sequential": 84 | layer = k_model.layers[0] 85 | return [(1,) + layer.input_shape[1:]] 86 | else: 87 | s_in = [] 88 | for layer in k_model.layers: 89 | if layer.__class__.__name__ == "InputLayer": 90 | s = layer.input_shape 91 | s_in.append((1,) + s[0][1:]) 92 | return s_in 93 | 94 | 95 | def tflite_convert_to_int8(model, data, type_io=None): 96 | """Quantize a Keras model""" 97 | 98 | print("Quantize the model (post-quantization) io_type={}".format(type_io), flush=True) 99 | 100 | converter = tf.lite.TFLiteConverter.from_keras_model(model) 101 | 102 | shape_inputs = _get_shape_inputs(model) 103 | 104 | def rep_data_gen(): 105 | for i in data[0:100]: 106 | f = np.reshape(i, shape_inputs[0]) 107 | tensor = tf.convert_to_tensor(f, tf.float32) 108 | yield [tensor] 109 | 110 | converter.representative_dataset = rep_data_gen 111 | converter.optimizations = [tf.lite.Optimize.DEFAULT] 112 | converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] 113 | 114 | if type_io: 115 | converter.inference_input_type = type_io[0] 116 | converter.inference_output_type = type_io[1] 117 | 118 | return converter.convert() 119 | 120 | 121 | # Load data set 122 | x, y, tx, ty = load_data() 123 | 124 | # Build and train a model 125 | model = build_model() 126 | model.fit(x, y, epochs=2, validation_split=0.1) 127 | 128 | print("Saving the model : ", "mnist_fp32.h5") 129 | model.save("mnist_fp32.h5") 130 | 131 | # test the model 132 | _, acc = model.evaluate(tx, ty, verbose=0) 133 | 134 | print("acc = {:.2f}".format(acc)) 135 | 136 | # post-quantize the model 137 | tf_q = tflite_convert_to_int8(model, x) 138 | 139 | print("Saving the model : ", "mnist_q_with_io_float.tflite") 140 | with open("mnist_q_with_io_float.tflite", "wb") as f: 141 | f.write(tf_q) 142 | -------------------------------------------------------------------------------- /scripts/tflite_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | # @attention 5 | # 6 | # Copyright (c) 2022 STMicroelectronics. 7 | # All rights reserved. 8 | # 9 | # This software is licensed under terms that can be found in the LICENSE file 10 | # in the root directory of this software component. 11 | # If no LICENSE file comes with this software, it is provided AS-IS. 12 | # 13 | 14 | """ 15 | Example to show how to use the Ai runner to compare 16 | the generated predictions from the C-model and the 17 | predictions generated by the TFLite interpreter. 18 | 19 | Input data can be randomly generated or provided by 20 | the user (Numpy npz format file). 21 | """ 22 | 23 | import sys 24 | import os 25 | import argparse 26 | from statistics import mean 27 | import numpy as np 28 | 29 | os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3" 30 | 31 | import tensorflow as tf 32 | 33 | from ai_runner import AiRunner 34 | 35 | _DEFAULT = "serial" 36 | 37 | 38 | def dequantize(q, scale, zp): 39 | """Dequantize the array""" 40 | return (q.astype(np.float32) - np.float32(zp)) * np.float32(scale) 41 | 42 | 43 | def stat_to_str(val): 44 | if val.dtype == np.float32: 45 | str = "min={:.9f}, max={:.9f}, mean={:.1f}, std={:.1f}".format( 46 | np.min(val), np.max(val), np.mean(val), np.std(val) 47 | ) 48 | else: 49 | str = "min={}, max={}, mean={:.1f}, std={:.1f}".format( 50 | np.min(val), np.max(val), np.mean(val), np.std(val) 51 | ) 52 | return str 53 | 54 | 55 | def rmse(ref, pred): 56 | """Return Root Mean Squared Error (RMSE).""" 57 | return np.sqrt(((ref.astype(np.float32) - pred.astype(np.float32)) ** 2).mean()) 58 | 59 | 60 | def l2r(ref, pred): 61 | """Compute L2 relative error""" 62 | 63 | def magnitude(v): 64 | return np.sqrt(np.sum(np.square(v).flatten())) 65 | 66 | mag = magnitude(pred.astype(np.float32)) + np.finfo(np.float32).eps 67 | return magnitude((ref.astype(np.float32) - pred.astype(np.float32))) / mag 68 | 69 | 70 | def generate_metrics(ref, pred, scale=1.0, zp=0, desc=None, plot=False): 71 | """Generate and display metrics""" 72 | 73 | assert ref.dtype == pred.dtype 74 | 75 | desc = "[{}]".format(str(desc)) if desc else "[]" 76 | b_size = ref.shape[0] 77 | 78 | ref = ref.flatten() 79 | pred = pred.flatten() 80 | 81 | if ref.dtype != np.float32: 82 | # integer data type 83 | ref_f = dequantize(ref, scale, zp) 84 | pred_f = dequantize(pred, scale, zp) 85 | rmse_f = rmse(ref_f, pred_f) 86 | l2r_f = l2r(ref_f, pred_f) 87 | d = ref.astype(np.int32) - pred.astype(np.int32) 88 | 89 | # histogram 90 | err = [] 91 | hist = {} 92 | for i in range(len(d)): 93 | if np.abs(d[i]) > 0: 94 | # err_ = np.abs(d[i]) 95 | err_ = d[i] 96 | err.extend([err_]) 97 | hist[err_] = hist.get(err_, 0) + 1 98 | else: 99 | # float32 data type 100 | d = ref - pred 101 | rmse_f = rmse(ref, pred) 102 | l2r_f = l2r(ref, pred) 103 | 104 | print("") 105 | print(f"{desc} - {b_size} samples, {ref.dtype}, {ref.size} items") 106 | print("-" * 80) 107 | if ref.dtype != np.float32: 108 | print(f" diff : {len(err)}/{len(ref)}, hist={hist}") 109 | print(" ref : {}".format(stat_to_str(ref))) 110 | print(" pred : {}".format(stat_to_str(pred))) 111 | print(" diff : {}".format(stat_to_str(d))) 112 | if ref.dtype != np.float32: 113 | print(" metrics : rmse={:.9f} l2r={:.9f} (quant.)".format(rmse(ref, pred), l2r(ref, pred))) 114 | print(" metrics : rmse={:.9f} l2r={:.9f} (dequant.)".format(rmse_f, l2r_f), flush=True) 115 | else: 116 | print(" metrics : rmse={:.9f} l2r={:.9f}".format(rmse_f, l2r_f), flush=True) 117 | 118 | if ref.dtype == np.float32: 119 | return 120 | 121 | if not len(err) or not plot: 122 | return 123 | 124 | import matplotlib.pyplot as plt 125 | 126 | # display histogram 127 | bins = [b for b in range(min(err), max(err) + 2)] 128 | plt.style.use("ggplot") 129 | plt.hist(np.array(err), bins=bins, density=False, align="left", rwidth=0.8) 130 | plt.xlabel("Value") 131 | plt.ylabel("Frequency") 132 | plt.title(f"Diff. histogram: {len(err)}/{len(d)} items") 133 | plt.show() 134 | 135 | return 136 | 137 | 138 | def tf_create(f_path, verbosity): 139 | 140 | if not f_path: 141 | return None 142 | 143 | print('\nCreate the interpreter for the "{}" model'.format(f_path)) 144 | 145 | tf_interpreter = tf.lite.Interpreter(model_path=f_path) 146 | tf_interpreter.allocate_tensors() 147 | 148 | input_details = tf_interpreter.get_input_details() 149 | output_details = tf_interpreter.get_output_details() 150 | 151 | if verbosity: 152 | 153 | def _tens_to_str(val): 154 | ext_ = "" 155 | if val.get("quantization", None): 156 | ext_ = ", scale={}, zp={}".format(val["quantization"][0], val["quantization"][1]) 157 | return "{}, {}{}".format(tuple(val["shape"]), val["dtype"], ext_) 158 | 159 | print("-" * 80) 160 | print("{:20s} : {}/{}".format("inputs/outputs", len(input_details), len(output_details))) 161 | for tens in input_details: 162 | print("{:20s} : {}".format(tens["name"], _tens_to_str(tens))) 163 | for tens in output_details: 164 | print("{:20s} : {}".format(tens["name"], _tens_to_str(tens))) 165 | print("-" * 80) 166 | 167 | return tf_interpreter 168 | 169 | 170 | def tf_run(tf_interpreter, inputs): 171 | 172 | assert len(tf_interpreter.get_input_details()) == 1 173 | 174 | input_details = tf_interpreter.get_input_details() 175 | output_details = tf_interpreter.get_output_details() 176 | batch_size = inputs[0].shape[0] 177 | 178 | # align the shape of the inputs (c-model is always - (b, h, w, c)) 179 | inputs[0] = inputs[0].reshape((-1,) + tuple(input_details[0]["shape"][1:])) 180 | 181 | for batch in range(batch_size): 182 | input = np.expand_dims(inputs[0][batch], axis=0) 183 | tf_interpreter.set_tensor(input_details[0]["index"], input) 184 | tf_interpreter.invoke() 185 | output = tf_interpreter.get_tensor(output_details[0]["index"]) 186 | if batch == 0: 187 | outputs = [output] 188 | else: 189 | outputs[0] = np.append(outputs[0], output, axis=0) 190 | return outputs 191 | 192 | 193 | def load_data(f_npz): 194 | 195 | val_data = np.load(f_npz) 196 | return [val_data["m_inputs_1"]] 197 | 198 | 199 | def test(args): 200 | 201 | # create the interpreters 202 | tf_interpreter = tf_create(args.model, args.verbosity) 203 | 204 | ai_runner = AiRunner(debug=args.debug) 205 | if not ai_runner.connect(args.desc): 206 | return 1 207 | 208 | ai_runner.summary(level=args.verbosity) 209 | 210 | # check input/output signatures 211 | assert len(tf_interpreter.get_input_details()) == 1 212 | assert tf_interpreter.get_input_details()[0]["dtype"] == ai_runner.get_input_infos()[0]["type"] 213 | # assert tuple(tf_interpreter.get_input_details()[0]['shape']) == ai_runner.get_input_infos()[0]['shape'] 214 | 215 | # generate input data 216 | if args.npz: 217 | (inputs,) = load_data(args.npz) 218 | inputs[0] = inputs[0].reshape((-1,) + ai_runner.get_input_infos()[0]["shape"][1:]) 219 | else: 220 | inputs = ai_runner.generate_rnd_inputs(batch_size=args.batch) 221 | 222 | # run the interpreters 223 | print("\nRunning the interpreters...", flush=True) 224 | 225 | outputs, profile = ai_runner.invoke(inputs) 226 | tf_outputs = tf_run(tf_interpreter, inputs) 227 | 228 | print("\n{} run-time profiling".format(profile["info"]["runtime"]["name"]), flush=True) 229 | print("-" * 80) 230 | print("host execution time : {:.3f}ms".format(profile["debug"]["host_duration"])) 231 | print("number of samples : {}".format(len(profile["c_durations"]))) 232 | print("inference time by sample : {:.3f}ms (average)".format(mean(profile["c_durations"]))) 233 | print("") 234 | 235 | # Compare results 236 | print("\nComparing results...", flush=True) 237 | 238 | for i, (tf_res, res) in enumerate(zip(tf_outputs, outputs)): 239 | tens = ai_runner.get_output_infos()[i] 240 | if tf_res.dtype == np.float32: 241 | desc = "{}".format(tens["name"]) 242 | generate_metrics(tf_res, res, desc=desc) 243 | np.testing.assert_almost_equal(tf_res, res.reshape(tf_res.shape), decimal=6) 244 | else: 245 | desc = "{}, scale={}, zp={}".format(tens["name"], tens["scale"], tens["zero_point"]) 246 | generate_metrics( 247 | tf_res, res, scale=tens["scale"], zp=tens["zero_point"], desc=desc, plot=args.plot 248 | ) 249 | print("") 250 | 251 | 252 | def main(): 253 | """ script entry point """ 254 | 255 | parser = argparse.ArgumentParser(description="Utility to test a generated TFlite model") 256 | parser.add_argument( 257 | "--model", "-m", metavar="STR", type=str, help="TFLite model file", default=None 258 | ) 259 | parser.add_argument( 260 | "--desc", 261 | "-d", 262 | metavar="STR", 263 | type=str, 264 | help="description for STM AI connection", 265 | default=_DEFAULT, 266 | ) 267 | parser.add_argument("--batch", "-b", metavar="INT", type=int, help="batch_size", default=2) 268 | parser.add_argument( 269 | "--verbosity", 270 | "-v", 271 | nargs="?", 272 | const=1, 273 | type=int, 274 | choices=range(0, 3), 275 | help="set verbosity level", 276 | default=0, 277 | ) 278 | 279 | parser.add_argument("--npz", metavar="STR", type=str, help="NPZ file", default=None) 280 | 281 | parser.add_argument("--debug", action="store_true", help="debug option") 282 | parser.add_argument("--plot", action="store_true", help="plot option") 283 | args = parser.parse_args() 284 | 285 | return test(args) 286 | 287 | 288 | if __name__ == "__main__": 289 | sys.exit(main()) 290 | --------------------------------------------------------------------------------