搜索
发新帖本帖赏金 100.00元(功能说明)我要提问
返回列表

[STM32F0] 【回归原创】开发过程中太多bug,整理一下最近的问题

[复制链接]
28721|10
手机看帖
扫描二维码
随时随地手机跟帖
呐咯密密|  楼主 | 2021-9-28 14:28 | 显示全部楼层 |阅读模式
[url=home.php?mod=space&uid=760190]@21小跑堂 #申请原创#[/url]

前言
离放假还有三天了,最近公司的事情太多,忽略了@21小跑堂 的原创,要不是最近跑堂的原创帖很多,感觉她都能杀过来逼我下笔了。因为最近一直在重复之前的工作,没有新的东西,索性给大家整理一下容易出现的问题。可能很多大佬都不认为是问题,但是我们这种新人,还是容易踩坑,索性潦草几笔灌水一篇,也能给跑堂一个交代。
背景:
真正的目的是给自己一个纠错记录,上文纯属调侃。最近老是忘事,遇到的bug,过几天再次遇到,就会忘了之前如何处理,遂留笔记一篇,也给后面可能遇到该问题的小伙伴一个借鉴。
问题汇总:
最近没得更新,主要是我们搞到了一批芯片,之前的项目可以重新提上日程,于是保留了之前的开发思路,在其他MCU平台上进行重新开发,遇到的问题是一件接着一件。首先产品端最初是STM32F030,现在的情况大家都了解,这颗料肯定是无法再用了,虽然手里还有几千片存货,可能一周都坚持不住,于是主控换成了GD32E230F4,主频更高,但是flash太小,我的代码编译之后会超出内存空间,此为所遇问题之一。我们有一个用于给产品配合的小玩意,一般一个客户有几个就行,小客户一个便可。之前为了开发快捷迅速,选择了STM32F103作为主控,所有功能开发完毕。但是因为这个小玩意是免费赠送,而且现在STM32F103也买不到,这个问题只有换芯片才能解决,于是换了GD32E230F4,同样面临代码空间不够的问题,而且还附带其他问题,此为其二。还有一个是用STM32F030遇到发送数据也会进入USART的空闲中断,无论代码如何处理。此为其三。
问题详情及解决之道:
问题一:
flash空间不足的问题我算是解决了一半,只能算解决了问题,而解决问题后所带来的其他问题,本人暂时无法追踪原因。
因为之前STM32F030的flash足够大,所以没遇到这个问题,在资源紧张的GD32E230中遇到了。但是在缺货的情况下,能找到一颗供应满足的MCU实属不易,想方设法也得用起来。
在代码编写完之后遇到如下问题:
847556152a0c260c63.png
21326152a0e17d192.png
我第一次遇到这种问题,去搜索发现是代码太大,无法烧录进MCU的FLASH。检查发现code的确超出容量了。
909366152a163d9850.png
于是借鉴网络上的方法提高优化等级。
278116152a1a650fdc.png 249906152a1c023bf8.png
可以发现明显变小,烧录也没问题,但是代码不正常运行,没有卡死在任何地方,但是确实功能异常,在debug后发现问题出在SPI通信,我使用DMA+SPI0,发送一个数组给传感器例如tx[3] = {0x01,0x02,0x03};然后接受数组可以正常接收到传感器数据rx[3] = {0x01,0x02,0x03},将优化等级提高到1,此时SPI收到的数据rx[3] = {0x03,0x01,0x02}。这就导致了我后面处理SPI数据的时候数据出错。于是我将发送的数据改为4个,也就是多发一个字节,此时接收到的数据是rx[4] = {0x00,0x01,0x02,0x03}。我在取数据的时候取后三个便可,这是一个治标不治本的办法,至今我没找到解决之道。
其实这个问题的根源就是硬件IIC的驱动太大了,我没能简化掉。但是发现提高优化等级可以将代码空间压缩,那FLASH不就有闲置空间了吗?为何还要用外置EEPROM呢?于是舍弃外置EEPROM,更换片内FLAH。
因为一页flash足够我用了,这里只写一页,下面的代码是参考官方例程自己简化的一个写FLASH的驱动,灰常好用。
void fmc_program(uint8_t* p_buffer,uint32_t Start_Address,uint16_t number_of_byte)
{
        uint32_t u32data;//fmc解锁
        fmc_unlock();
        fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR);
    fmc_page_erase(ERASE_PAGE_START_ADDR);
        address = PROGRAM_ADDRESS;
        for(uint16_t i = 0;i<number_of_byte;i++)
        {       
                u32data = (uint32_t)p_buffer[i];
                fmc_word_program(address, u32data);
                address+= 4U;
                fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR);
        }
       
        fmc_lock();        //fmc上锁
}
GD的FLASH例程叫FMC,一开始都没找到,以为例程没有。过程很简单:
1.使用库函数fmc_unlock();函数将FLAH解锁,
2.使用库函数清标志位fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR);
3.使用库函数fmc_page_erase(ERASE_PAGE_START_ADDR);擦除一页,写之前必须先擦除,而且一擦就是整页,这里我有个内容没写,是需要先将原来的数据读出来的,否则会造成不需要改的数据擦掉。读数据直接取地址就行,将数据全读到一个数组中,然后在数组中将需要改的数据修改,调用这个驱动进行写便可。ERASE_PAGE_START_ADDR为该页的首地址。
4.调用函数fmc_word_program(address, u32data);循环写入,我是从页首开始写,这个参数address就是上面的ERASE_PAGE_START_ADDR。
5.写完重新置位标志位并上锁。
uint32_t data;
        address = PROGRAM_ADDRESS;
        for(uint16_t j=0;j<256;j++)//取出所有FLASH里面的数据
        {
                data = *(uint32_t*)address;
                i2c_rxbuff[j] = (uint8_t)data;       
                address += 4U;
        }
上面是将整页数据读出放在数组i2c_rxbuff中。

这里忽然想到还有一个问题,这里得说一下:我的工程用到了IIC,目的是像24C04里面写数据,但是我的项目要求没有足够的时间给我写,每个上位机的指令过来我必须及时回复,间隔时间只有几十微秒,而写24c04需要的是ms级别的时间,而且GD32E230没有足够的DMA通道给我使用,会和URAT以及SPI的DMA冲突。于是挤压了一点时间出来,在主循环执行IIC写操作,其他应用用DMA处理,这样每个指令之间都可以空出一点点时间来写,慢慢写呗,不影响正常通信就行。但是在调试的时候发现了一个问题,这个问题很严重,但是不会影响我之前的应用,前提是我不在主循环进行IIC的读写。
问题很简单,我退出不了串口接收中断,这个问题在一般应用中很常见,但是因为项目需求的原因,我所有的应用都在中断内完成,没有中断外的应用,都是一个中断打断另一个中断。最后还是在论坛里找到了答案。这一点在GD的例程中是没有体现的,感谢这位兄弟的经验。
541546152a6828ebc1.png

问题二:
代码空间不足的问题上文已经处理,这里不赘述。这里说一下其他问题。
我们的产品为例节省成本,基本都是使用MCU内部时钟,之前ST是,现在GD也是,所用外设为:USRAT,SPI,IIC。均无任何问题。但是在芯片荒之前用STM32F103做这个小玩意时加上了外部晶振,而这次改用GD32E230再次取消外部晶振,于是遇到了大问题。我通过定时器触发SPI采集若干个数据,在MCU内部进行算法处理,得到的值有问题,我怀疑是MCU计算出错,毕竟里面包括了浮点运算,三角函数等等。于是我将数据导入到EXCLE中,发现计算并无问题。最后问题定位在定时器不准,在使用内部时钟时,其他通信外设没有问题,我就觉得内部时钟是可靠的,但是遇到定时器他就歇菜了。于是重新打板,问题得以解决。
还有个问题就是很容易出现的SPI通信问题,在产品上,MCU和传感器是在同一个PCB上,距离很近,用100Khz的通信速率可以读写传感器内部EEPROM,但是用这个小玩意和产品通信时通过排线连接,100K的通信速率会导致通信失败,降低通信速率,将速率降低到50K便可。

问题三:
发送数据进入串口接收中断直到写这篇帖子之前才找到原因,在网上没找到这个问题的解决之道,也怀疑过时清标志位的问题,但是无论我如何操作,都无法解决这个问题。然后用示波器点了一下rx
864836152af991c8bd.png
明明在发送数据,但是却有一个下降沿,然后再看空闲中断的定义:空闲中断是接收数据后出现一个byte的高电平(空闲)状态,就会触发空闲中断.并不是空闲就会一直中断,准确的说应该是上升沿(停止位)后一个byte,如果一直是低电平是不会触发空闲中断的。
因为这一个电平的下拉,导致电平回拉的时候产生了一个上升沿,导致误判为空闲状态。查看电路图,发现了一颗碍事的下拉电阻。
181646152b061d7647.png
于是将该电阻拆掉便可,这个问题之所以一直未发现,其实是之前所有的应用都用不到空闲中断,电路一直这么设计并无问题,但是在空闲中断应用中就会导致出错。ps:硬件不是我设计,所以这个问题发现的比较晚,而且我之前发现这个问题后在软件上做处理给抵消了。不影响使用。今天没事才来找原因。

写在最后的话:
这篇文章对很多人来说没多大意义,此篇为了记录一下自己的经验,其实在写到这里的时候自己都感觉自己当时有点呆,但是身处当时的环境下,自己真的找不到问题点,因为当时太多的因素都会导致出问题,一步步排查才出结果,很多东西我不能发出来,所以看起来这些问题都很简单。求大佬勿喷。

使用特权

评论回复

打赏榜单

21小跑堂 打赏了 100.00 元 2021-09-29
理由:恭喜通过原创文章审核!请多多加油!

Bobby13| | 2021-9-28 14:40 | 显示全部楼层
记录下问题和改进,就是给自己积累,给公司积累,给国家积累

使用特权

评论回复
呐咯密密|  楼主 | 2021-9-28 14:58 | 显示全部楼层
Bobby13 发表于 2021-9-28 14:40
记录下问题和改进,就是给自己积累,给公司积累,给国家积累

我的天,大佬说话也太好听了。

使用特权

评论回复
logan0279| | 2021-9-30 11:22 | 显示全部楼层
不错不错,感谢分享。

使用特权

评论回复
Gavin3389| | 2021-9-30 17:04 | 显示全部楼层
放假了,啥也不干了,在家听雨~~

使用特权

评论回复
呐咯密密|  楼主 | 2021-9-30 17:07 | 显示全部楼层
Gavin3389 发表于 2021-9-30 17:04
放假了,啥也不干了,在家听雨~~

还有雨听。我这边都不下雨,我也准备躺好了休息,啥也不干了,这段时间搞累了

使用特权

评论回复
呈兴| | 2021-9-30 23:30 | 显示全部楼层
哇塞!大神,写的太好了。我就没这耐心。

使用特权

评论回复
Gavin3389| | 2021-10-8 17:54 | 显示全部楼层
呐咯密密 发表于 2021-9-30 17:07
还有雨听。我这边都不下雨,我也准备躺好了休息,啥也不干了,这段时间搞累了 ...

雨下大劲了,感冒了~~
节后综合症也来了~~

使用特权

评论回复
caoenq| | 2021-10-9 09:14 | 显示全部楼层
问题二,内部定时器不准的问题,重新打板能解决?

使用特权

评论回复
呐咯密密|  楼主 | 2021-10-9 09:32 | 显示全部楼层
caoenq 发表于 2021-10-9 09:14
问题二,内部定时器不准的问题,重新打板能解决?

重新打板用外部晶振,之前的板子上没有预留晶振焊盘

使用特权

评论回复
caoenq| | 2021-10-9 09:40 | 显示全部楼层
呐咯密密 发表于 2021-10-9 09:32
重新打板用外部晶振,之前的板子上没有预留晶振焊盘

哦哦

使用特权

评论回复
返回列表 发新帖 本帖赏金 100.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

本版热帖

本版活跃用户

优质原创写原创,赢大奖

编辑推荐

  • 1 呐咯密密 得到打赏 ¥310.00
  • 2 qbwww 得到打赏 ¥265.00
  • 3 yanzhengxin1 得到打赏 ¥200.00
  • 4 full_stack 得到打赏 ¥100.00
  • 5 laocuo1142 得到打赏 ¥55.00
  • 6 zhangjiantao 得到打赏 ¥50.00
  • 7 小叶三千 得到打赏 ¥50.00
  • 8 cjseng 得到打赏 ¥50.00
  • 9 改名了 得到打赏 ¥30.00
  • 10 HXM1593 得到打赏 ¥15.00
在线客服 快速回复 返回顶部 返回列表