历史上的今天
今天是:2025年07月31日(星期四)
2019年07月31日 | STM32CubeMx生成的工程中使用Printf函数调试和IAP
2019-07-31 来源:eefocus
一、STM调试信息打印方法。
1. 新建stm32cubemx工程,配置工程。

我用的是STM32cubeMx版本: Version 4.27.0, cube Version V1.0。

2. 在stm32cubemx工程,配置工程,勾选使用FreeRtOs系统。

注意,勾选左边的,freertos,使用系统。stm32做的,非常方便。
3. 生成带系统FreeRtos的源码工程(我这里基于keil MDK v5)

4. 生成工程,然后用keil打开,在源码里面添加代码,使得USART1重定向到标准Printf函数中输出。

在generated file里面,勾选:generate periheral initialization as apair of “.c/.h” files per periheral; 这样可以让每个外设,都生成一个文件。不用全面功能呢堆在一起。


注意选择工程的种类,我用的是keil mdk v5。
5. 总结添加的代码如下:
记得包含标准输入输入头文件: stdio.h
在usart.c里面添加:
/* USER CODE BEGIN 0 */
#include /* USER CODE END 0 */ /* USER CODE BEGIN 1 */ #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif PUTCHAR_PROTOTYPE { HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF); return ch; } /* USER CODE END 1 */ 在“user code” 里面添加,这样你再次编译生成stm32cubmx工程的时候,你的代码才会被保留,不如会被知覆盖掉。 二、STM IAP方法(基于STM32F0xx系列)。 1. stm32f0x系列IAP,基于Stm32CubeMx的工程。 下面说明如何基于stm32f0x系统里面,使用在线升级(stm32f0 IAP) Bootloader里面,main里调用函数跳转到APP地址0x8003000,下面的这个是main函数里面的主程序,分开烧录下载,一般来说,先下载这个程序用于做IAP的。 typedef void (*pFunction)(void); #define ApplicationAddress 0x8003000 void UserAppStart(void)//这里是bootloader里面的函数 { if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000) { /* Jump to user application */ JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); Jump_To_Application = (pFunction) JumpAddress;//跳转到0x8003000 /* Initialize user application's Stack Pointer */ __set_MSP(*(__IO uint32_t*) ApplicationAddress);////初始化用户程序的堆栈指针 Jump_To_Application();//执行跳转,程序从0x8003000开始跑。 } } void main(void) { /*加入一些判断,或者*/ UserAppStart; } stm23cubemx 工程源码里面(APP) main 函数添加: #define APPLICATION_ADDRESS (uint32_t)0x08003000 /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ #if (defined ( __CC_ARM )) __IO uint32_t VectorTable[48] __attribute__((at(0x20000000))); #elif (defined (__ICCARM__)) #pragma location = 0x20000000 __no_init __IO uint32_t VectorTable[48]; #elif defined ( __GNUC__ ) __IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable"))); #endif // 上面是要自己添加的 int main(void) { //自己添加的,最好在user code里面添加,不会被覆盖 /* USER CODE BEGIN 1 */ uint32_t i = 0; /* USER CODE END 1 */ HAL_Init(); /* Configure the system clock to 48 MHz */ SystemClock_Config(); /* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/ /* Copy the vector table from the Flash (mapped at the base of the application load address 0x08004000) to the base address of the SRAM at 0x20000000. */ for(i = 0; i < 48; i++) { VectorTable[i] = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2)); } /* Enable the SYSCFG peripheral clock*/ __HAL_RCC_SYSCFG_CLK_ENABLE(); /* Remap SRAM at 0x00000000 */ //拷贝中断向量到 VectorTable,stm32f0 没有中断偏移寄存器,所以将中断向量表读取到RAM中,然后重映射到RAM地址. __HAL_SYSCFG_REMAPMEMORY_SRAM(); /* Add your own code here... */ // 接下来做自己的事情,这里忽略不写........... } 在Keil下设置IROM1:start 0x8003000 IRAM1:Start 0x200000C0 记得对应自己设置的位置。 stm32f0 没有中断偏移寄存器,所以将中断向量表读取到RAM中,然后重映射到RAM地址, 应该说,stm32f0x系列的都要这样做,否则不能正常使用中断。 2. stm32f1+系列IAP,基于Stm32CubeMx的工程。 stm32F103 dfu IAP #define ApplicationAddress 0x08005000 typedef void (*pFunction)(void); int main(void) { DFU_Button_Config(); /* DFU Button Check */ if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8) == 0) { // Test if user code is programmed starting from address 0x8005000 // if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000) { // Jump to user application // JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); Jump_To_Application = (pFunction) JumpAddress; // Initialize user application's Stack Pointer // __set_MSP(*(__IO uint32_t*) ApplicationAddress); Jump_To_Application(); } } 这里不用重映射向量表,只需要跳转就好了。这个使用于stm32F1,stm32F2等单片机的dfu升级和在线升级。同样,需要在Keil中的"Target"设定IROM1的气势地址和结束地址, 一般来说,设置起始地址: 0x8003000,或者0x8005000都可以,主要是看你的IAP程序有多大。 注意! 上面并非在线固件升级,而只是,修改bootloader,如果需要在线usb DFU升级,那么要用到Stm32fCubeMx的 dfu功能, 幸运的是,我们不需要在去折腾stm32寄存器,而用stm32cubemx直接生成dfu功能的代码了,详细见下面: 三、 STM32CubeMx Device firmware Update(STM32 DFU功能实现) 1. demo:STM32F103VBT单片机的dfu IAP功能的实现详细步骤(基于Stm32cubeMx): 先打开Stm32CubeMx软件,然后选择型号,stm32f103vbt,在左侧配置功能的界面,打开usb device(STM32F103VBt只有 usb Device only功能) 版本版本有依旧之前一样。 2. 配置STM32F103VBT单片机的DFU(这里默认配置即可),启动地址一般位于0x08000000: 3. 生成工程,就万事大吉,启动开发板,你会发现需要你安装usb驱动, 4. 下载编译好的stm32cubemx工程DFU hex文件到开发板验证: 然后上电启动,连开发板的usb到电脑,发现,电脑发现新硬件!需要安装smt32 的dfu驱动, 这个驱动在你的DFU下载软件DfuSeDemo的安装文件夹里面可以找到。 安装好驱动之后,就可以用那个来下载主程序了! 记得修改dfu里面的跳转(这样你才能有跑到你的应用程序的main函数去),参考上一个步骤,开始你的产品程序编写吧!







史海拾趣
|
本人做过技术开发工作多年,从焊电路板的小工程师逐渐做到项目经理、研发经理,现在做到总工程师,作为工程师有亲身的感受,作为研发主管,对工程师的性格、心理和知识结构有非常深入的了解,现在把自己的一点感悟与大家分享,希望大家批评指正,欢 ...… 查看全部问答> |
|
从70年代末的简单控制发展到今天的高端应用,嵌入式系统已经变成一个复杂的高技术系统,要在短时间开发出所需功能的难度大大提升,但是市场竞争又要求产品能够快速面市同时必须确保产品的质量和性能,这里面工具就起着很重要的作用。这其中,对工具 ...… 查看全部问答> |
|
EXTERN XBYTE gxbUartBitNum _AT_ (0x990F);/////当前接受数据的位数 EXTERN XBYTE gxbUart2s _AT_ (0x991F); //ie. SBUF2 EXTERN XBYTE gxbUart2f ...… 查看全部问答> |
|
BeagleBone 硬件性能测试(1) ---- 我是出来打酱油的 今天惊问BeagleBone的测试最终名单居然有我, 有点受宠若惊,同时诚惶诚恐的感觉。.最近确实事情比较多,怕耽误测试的效果;同时也希望有人能够关注一下硬件的实际性能。本来只想做条鲶鱼,趟趟浑水,打打酱油。没想到居然就上了,汗颜啊!亚历山大 ...… 查看全部问答> |
|
上电(mp/mc=0)-->bootrom(判断引脚状态)-->flash(3f7ff6.跳转指令)-->_c_init00-->main()-->memcopy()[此函数的作用是将不能在flash里之行的程序段复制到rom里]-->initflash()[此函数必须在rom里执行]-->while(1);… 查看全部问答> |




