GD32F4移植STM32F4

[复制链接]
 楼主| c17 发表于 2023-8-27 01:11 | 显示全部楼层
或者

/* Authorize the small information block programming */
FLASH->OPTKEYR = FLASH_KEY1;
FLASH->OPTKEYR = FLASH_KEY2;
__NOP();
__NOP();
 楼主| c17 发表于 2023-8-27 01:11 | 显示全部楼层
3.2 F4的Flash修改
由于我代码里对Flash的操作使用的是正点原子的驱动文件,并未使用ST官方库函数stm32f4xx_flash.c,尝试搜索key( FLASH->OPTKEYR = FLASH_KEY1;FLASH->OPTKEYR = FLASH_KEY2;),并无匹配项,于是尝试搜索FLASH_KEY1,这时匹配到下面那个函数:
 楼主| c17 发表于 2023-8-27 01:11 | 显示全部楼层
  1. //解锁STM32的FLASH
  2. void STMFLASH_Unlock(void)
  3. {
  4.         FLASH->KEYR=FLASH_KEY1;        //写入解锁序列.
  5.         FLASH->KEYR=FLASH_KEY2;
  6. }
 楼主| c17 发表于 2023-8-27 01:12 | 显示全部楼层
于是便在其后面加了一个延时查询指令:while( ! (FLASH->CR & 0x200 ) );// Wait OPTWRE
但在后面的测试中,发现有较大概率会卡死在这个while循环中,于是只能采取加两个空延时的方式实现,具体是什么问题暂时还没有查出来。目前该函数改成以下这样:
 楼主| c17 发表于 2023-8-27 01:12 | 显示全部楼层
  1. //解锁STM32的FLASH
  2. void STMFLASH_Unlock(void)
  3. {
  4.         FLASH->KEYR=FLASH_KEY1;        //写入解锁序列.
  5.         FLASH->KEYR=FLASH_KEY2;
  6.         __NOP();
  7.         __NOP();
  8. //        while(!(FLASH->CR & 0x200));// Wait OPTWRE
  9. }
 楼主| c17 发表于 2023-8-27 01:12 | 显示全部楼层
此外在F1的帖子里,提到GD的延时时间比ST的短,出于保险起见,我在flash的操作中也延长了其等待时间,其函数的等待因为是可以break循环而提前退出,所以我也不知道这部分代码是否起到作用,但是加上应该不会有问题。我是将STMFLASH_WaitDone这个函数的参数扩大为原来的2倍,修改的函数如下:
 楼主| c17 发表于 2023-8-27 01:12 | 显示全部楼层
  1. //擦除扇区
  2. //sectoraddr:扇区地址,范围是:0~11.
  3. //0~3,16K扇区;4,64K扇区;5~11,128K扇区.
  4. //返回值:执行情况
  5. u8 STMFLASH_EraseSector(u32 sectoraddr)
  6. {
  7.         u8 res=0;
  8.         //res=STMFLASH_WaitDone(200000);//等待上次操作结束,最大2s
  9.         res=STMFLASH_WaitDone(400000);//等待上次操作结束,最大2s
  10.         if(res==0)
  11.         {
  12.                 FLASH->CR&=~(3<<8);        //清除PSIZE原来的设置
  13.                 FLASH->CR|=2<<8;        //设置为32bit宽,确保VCC=2.7~3.6V之间!!
  14.                 FLASH->CR&=~(0X1F<<3);//清除原来的设置
  15.                 FLASH->CR|=sectoraddr<<3;//设置要擦除的扇区
  16.                 FLASH->CR|=1<<1;        //扇区擦除
  17.                 FLASH->CR|=1<<16;        //开始擦除                  
  18.                 //res=STMFLASH_WaitDone(200000);//等待上次操作结束,最大2s
  19.                 res=STMFLASH_WaitDone(400000);//等待操作结束,最大2s  
  20.                 if(res!=1)                        //非忙
  21.                 {
  22.                         FLASH->CR&=~(1<<1);//清除扇区擦除标志.
  23.                 }
  24.         }
  25.         return res;
  26. }
  27. //在FLASH指定地址写一个字
  28. //faddr:指定地址(此地址必须为4的倍数!!)
  29. //dat:要写入的数据
  30. //返回值:0,写入成功
  31. //    其他,写入失败
  32. u8 STMFLASH_WriteWord(u32 faddr, u32 dat)
  33. {
  34.         u8 res;                     
  35.         //res=STMFLASH_WaitDone(0xFF);
  36.         res=STMFLASH_WaitDone(0X200);
  37.         if(res==0)//OK
  38.         {
  39.                 FLASH->CR&=~(3<<8);        //清除PSIZE原来的设置
  40.                 FLASH->CR|=2<<8;        //设置为32bit宽,确保VCC=2.7~3.6V之间!!
  41.                 FLASH->CR|=1<<0;        //编程使能
  42.                 *(vu32*)faddr=dat;        //写入数据
  43.                 //res=STMFLASH_WaitDone(0XFF);//等待操作完成,一个字编程,最多100us.
  44.                 res=STMFLASH_WaitDone(0X200);//等待操作完成,一个字编程,最多100us.//0xff
  45.                 if(res!=1)//操作成功
  46.                 {
  47.                         FLASH->CR&=~(1<<0);//清除PG位.
  48.                 }
  49.         }
  50.         return res;
  51. }
 楼主| c17 发表于 2023-8-27 01:12 | 显示全部楼层
4.其他修改
本来我以为修改以上几点就可以完美兼容代码,可现实给我一个大大的教训,现在想来可能是GD的芯片代码要更加规范,所以如果移植出问题了,可能要在代码的规范上重视。
还有就是GD的MCU和ST的相比在连续串口发送的时候会多一个IDLE bit,但是在F1中,这个差异对于大多数程序并不影响执行,所以就没有重视这个问题。
 楼主| c17 发表于 2023-8-27 01:12 | 显示全部楼层
4.1 函数中的变量定义
在函数中的变量必须先定义,再进行其他操作,当我的芯片改为GD之后,keil编译一遍程序之后,出现了几个报错,百度了一下,发现就是有一个变量的声明在函数的中间,将其声明改到函数前面之后就正常了。
 楼主| c17 发表于 2023-8-27 01:12 | 显示全部楼层
4.2 串口发送
在串口发送数据时,要先发送再等待相应的标志位变化,如果先查询标志位那么程序就会一直在这个while循环中运行,直到我的看门狗将程序复位。
 楼主| c17 发表于 2023-8-27 01:13 | 显示全部楼层
比如,我修改前的串口3发送代码如下:
  1. /*-------------------------------------------------*/
  2. /*函数名:串口3发送缓冲区中的数据                  */
  3. /*参  数:data:数据                               */
  4. /*返回值:无                                       */
  5. /*-------------------------------------------------*/
  6. void u3_TxData(unsigned char *data)
  7. {
  8.         int        i;       
  9.         while((USART3->SR&0X40)==0);
  10.         for(i = 1;i <= data[0];i ++){                       
  11.                 USART3->DR = data[i];
  12.                 while((USART3->SR&0X40)==0);       
  13.         }
  14. }
 楼主| c17 发表于 2023-8-27 01:13 | 显示全部楼层
修改之后为,就正常了。
  1. /*-------------------------------------------------*/
  2. /*函数名:串口3发送缓冲区中的数据                  */
  3. /*参  数:data:数据                               */
  4. /*返回值:无                                       */
  5. /*-------------------------------------------------*/
  6. void u3_TxData(unsigned char *data)
  7. {
  8.         int        i;       
  9. //        while((USART3->SR&0X40)==0);
  10.         for(i = 1;i <= data[0];i ++){                       
  11. //                USART3->DR = data[i];
  12. //                while((USART3->SR&0X40)==0);       
  13.                 USART_SendData(USART3,data[i]);
  14.     while( USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET );
  15.         }
  16. }
 楼主| c17 发表于 2023-8-27 01:13 | 显示全部楼层
4.3 中断服务函数中不能有printf
其实这个问题,是大部分做单片机开发的一个常识,这个是我之前在ST调试时留下的一条调试信息,只输出了一个数字,(因为我也知道中断中最好不能printf),在ST中正常,后面程序就忘了删,就埋了一个雷,浪费了许多时间。
这也是我说GD的代码要规范的原因,可能他的容错性还是低于ST的,还有其他的例子,但是我一时想不起来了,只能把我记得的bug写出来,以后调试出现问题,要着重查查代码规范性。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部
快速回复 在线客服 返回列表 返回顶部