I create a STM32CubeMX based STM32F407VET project, and try to use printf in project:
int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); /* USER CODE BEGIN 2 */ printf("Hello semihosting!\n"); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ printf("Hello semihosting!\n"); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
# List different hardware targets that are used to deploy the solution. target-types: - type: STM32F407VETx device: STM32F407VETx target-set: - set: images: - project-context: Project.Debug debugger: name: ST-Link@pyOCD clock: 4000000 protocol: swd telnet: - mode: monitor
20 11 03 00 08 a9 2a 00 08 79 2a 00 08 a5 2a 00 08 39 1f
I tested this on an STM32F769I-DISCO project. I started from the CubeMX basic Solution template, generated the code with STM32CubeMX without any extra configuration, selected Telnet/Serial Monitor in Mange Solution and added a simple printf() for semihosting output.
The output appeared when I connected the VS Code Serial Monitor to the pyOCD STDIO/Telnet TCP port, as shown in the screenshot. So I would suggest checking the Serial Monitor settings first.
Note: the port number 4444 is reserved in Keil Studio for semihosting, and it can be checked in the generated *.cbuild-run.yml.
One extra thing I had to fix was the CubeMX-generated MDK startup file. The startup file still had a non-microlib __user_initial_stackheap block. With AC6 linker scripts, the heap and stack are already provided by ARM_LIB_HEAP and ARM_LIB_STACK, so this old block can conflict with the linker-script setup. In my case, removing the non-microlib __user_initial_stackheap block from startup_stm32f769xx.s fixed standard printf(), preventing from HardFault. So it may be worth checking that block as well.
Thanks! The problem is the User Stack and Heap initialization part in startup_stm32f407xx.s, it can output correctly if I remove this part.
Glad to hear that it works on your side as well.
Quick addition: if you'd rather not touch the startup file at all, you can fix it from the linker script side instead. Keep the startup's STACK/HEAP areas and __user_initial_stackheap as they are, and just tell the default scatter file to place them instead of reserving its own:
// replace ARM_LIB_HEAP / ARM_LIB_STACK with: STARTUP_HEAP AlignExpr(+0, 8) { *(HEAP) } STARTUP_STACK AlignExpr(+0, 8) { *(STACK) }
Either way, pick one place (startup code or linker script) to manage them and keep it consistent.