STM32问题记录(一):下载、编译、仿真相关

0. 概述

本文主要记录一些STM32使用过程中遇到的问题,不定期更新补充。
有些问题可能并不是技术问题,但是遇到也是一种经历,也记录下来,以供后续参考吧。
点击进入:官网下载keil MDK最新版本、历史版本和芯片pack包
点击进入:STM32相关手册使用记录

1. 下载相关

1.1 使用STM32CubeMX生成工程,下载一次后无法继续下载?

在这里插入图片描述
提示复位失败。使用镊子短接复位按键–点击下载–立即松开镊子–下载成功。最终查找,是因为STM32CubeMX默认关闭了调试模式。需要根据下载方式,选择对应的选项。
在这里插入图片描述

1.2 下载程序过程中擦除失败

在这里插入图片描述
试了几次,都是擦除到0x08040000H,也就是256K。果不其然,MCU焊接的小容量,应该焊接512K。。。。

1.3 突然无法下载程序

给板子下载程序时,无法下载。提示如下:
在这里插入图片描述
用镊子短接了复位电路的电容,发现没有效果。更换一个j-link试下,就下载成功了。。。

2. Bootloader实现

单独写为一篇:STM32的Bootloader实现和遇到的情况

3. 仿真调试相关

3.1 定位hardfault问题和遇到的情况

单独写为一篇:Keil环境下STM32定位hardfault位置方法和遇到的情况

3.2 程序无法运行停留在"BKPT 0xAB"

添加部分功能后发现程序没有正常运行,调试看到并没有进入到main函数,完全没有运行:
在这里插入图片描述
反复查看了代码,没有发现明显问题。发现这时候连续点击全速运行,又能正常运行起来。最终找到解决办法:Stm32 debug停留在"BKPT 0xAB"或者"SWI 0xAB"的解决办法
文中提出三种方法,魔术棒勾选micro lib最简单(文中作者并不推荐)。测试可正常运行。
在这里插入图片描述
2022-1-26更新
程序中引入了一个开源库,调试中又出现了这个问题,但是已经勾选了微库。程序开始能够运行,在开源相关部分,会出现BKPT 0xAB。经过查找,发现是使用的开源库中使用了:

#define AT_DEBUG(...)          printf("[AT]:");printf(__VA_ARGS__) /*do{}while(0)*/

而我的程序中使用jlink进行打印,没有重定向到printf。试着将此处的printf修改为我自己的jlink打印语句,可以正常运行了。
经过这两次可以看到,出现该问题,多半是与printf有关。

4 编译相关

4.1 优化等级导致函数未调用 - 编译生成lib

调试发现程序调用lib库的函数,程序出现异常。使用lib的源文件调试,发现函数调用未生效:
在这里插入图片描述
将优化等级从-O3降到-O1,则正常:
在这里插入图片描述
为什么会导致函数调用不生效???
最终将文件修改优化等级,重新编译lib文件。
编译方法:Keil 下生成LIB库文件以及如何使用LIB库文件

4.2 warning: #870-D:invalid multibyte character sequence

在这里插入图片描述
搜了一圈,都是说汉字编码原因,这里不是汉字呀,明明是uint8_t
不过试了下,解决办法是通用的:让keil屏蔽掉这个类型的warning输出。在报警告的.c源文件中增加宏定义:

#pragma diag_suppress 870

更新:找到原因了,一直关注变量的类型,其实是打印的字符串,冒号使用了中文。修改为英文的冒号,就不必使用#pragma diag_suppress 870来屏蔽警告了。

4.3 error: #5: cannot open source input file “stm32f10x_lib.h“

使用keil5编译keil4工程报错,单独记为一篇:点击进入

5. FLASH存储相关

5.1 FLASH擦除返回成功,但读取仍然为原来的值

//2022.2.10
最近编写STM32G0B1芯片的bsp,调试flash时发现擦除异常,虽然HAL_FLASHEx_Erase返回HAL_OK,但此时读取仍然为之前写入的值。
驱动在之前的工程上是使用过的,又参考了下rtthread中的drv_flash_g0.c,也没有明显问题。
在这里插入图片描述
网上搜了一下,基本都是擦除函数返回就异常了。STM32L476 HAL_FLASHEx_Erase() 问题出现了同样的问题,表示将程序下载到开发板就成功了。开发板MCU型号不完全一致,但是同一系列。

查看下STM32G0B1的官方demo(STM32 HAL库手册获取和查阅方法以及查看官方例程),才发现我的程序少赋值一个结构体成员:
在这里插入图片描述
参考demo,对banks成员赋值,可以正常擦除了。

那么rtthread这里是没有做区分吗?还是我的理解仍然有问题?如果在STM32G0B1上运行,需要针对修改?以后用到了再来补充。

5.2 关于使用__attribute__进行版本号判断、固件防呆attribute

单独写为一篇:STM32定义数组到flash的指定位置

5.3 STM32是小端模式

在数据传输中经常会遇到大小端问题。STM32是小端模式,也就是数据的高字节保存在内存的高地址中,低字节保存在内存的低地址中。如一个32位无符号数0x12345678,从低地址到高地址依次储存 78h 56h 34h 12h参考链接)。
数据传输时为了方便取数据,常会用到联合体:

typedef union {
    uint16_t data_16;
    uint8_t data_8[2];
} uni_data_16_t;

在放置数据时就需要注意顺序:

    uni_data_16_t data16 = {0};
    
    data16.data_8[0] = node_id >> 8;
    data16.data_8[1] = node_id;
    reg[0] = data16.data_16;

串口通信在接收端:

node_id  = (body[0] << 8) + body[1];

6 延时相关

6.1 HAL_Delay出现死循环 - 未解决

出现HAL_Delay无法退出:
在这里插入图片描述
发现是uwTick没有自增:
在这里插入图片描述

6.2 使用nop()函数进行延时

// 2022.11.15
MCU:N32G031
在移植一些驱动程序时,经常会见到使用while或者for循环实现的简单delay函数,例如:

void soft_delay_us(uint16_t nus) 
{
    uint16_t us = 0;
    
    while(nus--)
    {
        us = 60;
        while(us--);
    }
}

但是这种方式,除了不够精确之外,还有一个问题:在程序开启较高优化等级之后,可能会被优化。下图是在keil等级优化-O3(左)和-O0(右)下的执行情况:
在这里插入图片描述
可以看到,优化等价为-O3的时候,函数体没有执行,直接退出了函数,没有达到期望的演示效果。大概是编译器认为此操作没有实际意义,所以不再执行?(搞清了再来补充)。
这里被优化了,于是改为使用nop函数。

相当于汇编里的nop伪指令,表示的是空操作,可是实现延时,表示执行一条没有什么意义的指令,例如 MOV r0 ,r0。因为是执行“指令”,所以花的时间是一个指令周期,指令周期是以机器周期为单位计算的(有的指令周期是2个或者以上的机器周期,但是nop指令就是花费一个机器周期),所以:1个NOP = 1个机器周期 = 12 * 时钟周期(51而言)= 12 * 1 / f; f 表示的是你的晶振频率,
例如6Mhz的晶振,f = 6000000,带入上式,结果单位为s。(点击进入

搜索了下,结果使用__NOP();__nop();__ASM volatile ("nop")都报错未定义。最终使用如下:

void soft_delay_us(uint16_t nus) 
{    
    while(nus--)
    {
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
        __asm("nop");
    }
}
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值