发新帖我要提问
12
返回列表
打印

GD32F4移植STM32F4

[复制链接]
楼主: c17
手机看帖
扫描二维码
随时随地手机跟帖
21
c17|  楼主 | 2023-8-27 01:11 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
或者

/* Authorize the small information block programming */
FLASH->OPTKEYR = FLASH_KEY1;
FLASH->OPTKEYR = FLASH_KEY2;
__NOP();
__NOP();

使用特权

评论回复
22
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,这时匹配到下面那个函数:

使用特权

评论回复
23
c17|  楼主 | 2023-8-27 01:11 | 只看该作者
//解锁STM32的FLASH
void STMFLASH_Unlock(void)
{
        FLASH->KEYR=FLASH_KEY1;        //写入解锁序列.
        FLASH->KEYR=FLASH_KEY2;
}

使用特权

评论回复
24
c17|  楼主 | 2023-8-27 01:12 | 只看该作者
于是便在其后面加了一个延时查询指令:while( ! (FLASH->CR & 0x200 ) );// Wait OPTWRE
但在后面的测试中,发现有较大概率会卡死在这个while循环中,于是只能采取加两个空延时的方式实现,具体是什么问题暂时还没有查出来。目前该函数改成以下这样:

使用特权

评论回复
25
c17|  楼主 | 2023-8-27 01:12 | 只看该作者
//解锁STM32的FLASH
void STMFLASH_Unlock(void)
{
        FLASH->KEYR=FLASH_KEY1;        //写入解锁序列.
        FLASH->KEYR=FLASH_KEY2;
        __NOP();
        __NOP();
//        while(!(FLASH->CR & 0x200));// Wait OPTWRE
}

使用特权

评论回复
26
c17|  楼主 | 2023-8-27 01:12 | 只看该作者
此外在F1的帖子里,提到GD的延时时间比ST的短,出于保险起见,我在flash的操作中也延长了其等待时间,其函数的等待因为是可以break循环而提前退出,所以我也不知道这部分代码是否起到作用,但是加上应该不会有问题。我是将STMFLASH_WaitDone这个函数的参数扩大为原来的2倍,修改的函数如下:

使用特权

评论回复
27
c17|  楼主 | 2023-8-27 01:12 | 只看该作者
//擦除扇区
//sectoraddr:扇区地址,范围是:0~11.
//0~3,16K扇区;4,64K扇区;5~11,128K扇区.
//返回值:执行情况
u8 STMFLASH_EraseSector(u32 sectoraddr)
{
        u8 res=0;
        //res=STMFLASH_WaitDone(200000);//等待上次操作结束,最大2s
        res=STMFLASH_WaitDone(400000);//等待上次操作结束,最大2s
        if(res==0)
        {
                FLASH->CR&=~(3<<8);        //清除PSIZE原来的设置
                FLASH->CR|=2<<8;        //设置为32bit宽,确保VCC=2.7~3.6V之间!!
                FLASH->CR&=~(0X1F<<3);//清除原来的设置
                FLASH->CR|=sectoraddr<<3;//设置要擦除的扇区
                FLASH->CR|=1<<1;        //扇区擦除
                FLASH->CR|=1<<16;        //开始擦除                  
                //res=STMFLASH_WaitDone(200000);//等待上次操作结束,最大2s
                res=STMFLASH_WaitDone(400000);//等待操作结束,最大2s  
                if(res!=1)                        //非忙
                {
                        FLASH->CR&=~(1<<1);//清除扇区擦除标志.
                }
        }
        return res;
}
//在FLASH指定地址写一个字
//faddr:指定地址(此地址必须为4的倍数!!)
//dat:要写入的数据
//返回值:0,写入成功
//    其他,写入失败
u8 STMFLASH_WriteWord(u32 faddr, u32 dat)
{
        u8 res;                     
        //res=STMFLASH_WaitDone(0xFF);
        res=STMFLASH_WaitDone(0X200);
        if(res==0)//OK
        {
                FLASH->CR&=~(3<<8);        //清除PSIZE原来的设置
                FLASH->CR|=2<<8;        //设置为32bit宽,确保VCC=2.7~3.6V之间!!
                FLASH->CR|=1<<0;        //编程使能
                *(vu32*)faddr=dat;        //写入数据
                //res=STMFLASH_WaitDone(0XFF);//等待操作完成,一个字编程,最多100us.
                res=STMFLASH_WaitDone(0X200);//等待操作完成,一个字编程,最多100us.//0xff
                if(res!=1)//操作成功
                {
                        FLASH->CR&=~(1<<0);//清除PG位.
                }
        }
        return res;
}

使用特权

评论回复
28
c17|  楼主 | 2023-8-27 01:12 | 只看该作者
4.其他修改
本来我以为修改以上几点就可以完美兼容代码,可现实给我一个大大的教训,现在想来可能是GD的芯片代码要更加规范,所以如果移植出问题了,可能要在代码的规范上重视。
还有就是GD的MCU和ST的相比在连续串口发送的时候会多一个IDLE bit,但是在F1中,这个差异对于大多数程序并不影响执行,所以就没有重视这个问题。

使用特权

评论回复
29
c17|  楼主 | 2023-8-27 01:12 | 只看该作者
4.1 函数中的变量定义
在函数中的变量必须先定义,再进行其他操作,当我的芯片改为GD之后,keil编译一遍程序之后,出现了几个报错,百度了一下,发现就是有一个变量的声明在函数的中间,将其声明改到函数前面之后就正常了。

使用特权

评论回复
30
c17|  楼主 | 2023-8-27 01:12 | 只看该作者
4.2 串口发送
在串口发送数据时,要先发送再等待相应的标志位变化,如果先查询标志位那么程序就会一直在这个while循环中运行,直到我的看门狗将程序复位。

使用特权

评论回复
31
c17|  楼主 | 2023-8-27 01:13 | 只看该作者
比如,我修改前的串口3发送代码如下:
/*-------------------------------------------------*/
/*函数名:串口3发送缓冲区中的数据                  */
/*参  数:data:数据                               */
/*返回值:无                                       */
/*-------------------------------------------------*/
void u3_TxData(unsigned char *data)
{
        int        i;       
        while((USART3->SR&0X40)==0);
        for(i = 1;i <= data[0];i ++){                       
                USART3->DR = data[i];
                while((USART3->SR&0X40)==0);       
        }
}

使用特权

评论回复
32
c17|  楼主 | 2023-8-27 01:13 | 只看该作者
修改之后为,就正常了。
/*-------------------------------------------------*/
/*函数名:串口3发送缓冲区中的数据                  */
/*参  数:data:数据                               */
/*返回值:无                                       */
/*-------------------------------------------------*/
void u3_TxData(unsigned char *data)
{
        int        i;       
//        while((USART3->SR&0X40)==0);
        for(i = 1;i <= data[0];i ++){                       
//                USART3->DR = data[i];
//                while((USART3->SR&0X40)==0);       
                USART_SendData(USART3,data[i]);
    while( USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET );
        }
}

使用特权

评论回复
33
c17|  楼主 | 2023-8-27 01:13 | 只看该作者
4.3 中断服务函数中不能有printf
其实这个问题,是大部分做单片机开发的一个常识,这个是我之前在ST调试时留下的一条调试信息,只输出了一个数字,(因为我也知道中断中最好不能printf),在ST中正常,后面程序就忘了删,就埋了一个雷,浪费了许多时间。
这也是我说GD的代码要规范的原因,可能他的容错性还是低于ST的,还有其他的例子,但是我一时想不起来了,只能把我记得的bug写出来,以后调试出现问题,要着重查查代码规范性。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则