查看: 372|回复: 2

[心得分享] GD大容量产品移植指南

[复制链接]

7

主题

0

好友

152

积分

童生

Rank: 2

  • TA的每日心情
    开心
    2016-5-12 15:06
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2016-5-16 16:10:03 |显示全部楼层
    2.软件移植注意事项
    2.1系统方面的注意事项
    2.1.1 HSE相关内容修改
    在V3.x的库,启动时间宏定义在xxx32f10x.h头文件中; 在V3.0以前的库,其启动时间宏定义在xxx32f10x_rcc.c中(HSEStartUp_TimeOut);

    修改前:
    //#define HSE_STARTUP_TIMEOUT        ((uint16_t)0x0500) /*!< Time out for HSE start up */
    修改后:       
    #define HSE_STARTUP_TIMEOUT        ((uint16_t)0xFFFF) /*!< Time out for HSE start up */
    修改原因:       
    GD和STM32的晶振部分电路设计有一定的差异,两者对外部高速晶振的参数要求也不一样,修改HSE_STARTUP_TIMEOUT宏定义可以保证晶振正常起振。当然你会在应用中发现有一些应用 不修改也能照常跑,这是由于晶振的参数差异造成了,为了保证程序的正常运行还是修改该宏定义。
    2.1.2 代码执行速度方面的修改
    GD32采用专利技术,提高了相同工作频率下的代码执行速度,带来了高性能的使用体验。这样一些 在ST下面编写的程序如While或者是For循环的延时,移植到GD上面来肯定相应的延时会变短。所以 如果客户的应用有用到这种延时方法的得根据实际情况进行一定的调整。GD的代码执行速度比ST 更快,那么在客户的应用中如果有一些判断的结构不够严谨也可能会导致问题。
    案例1:
    客户在软件中编写了一个延时函数如下: void delay(void)
    {
    u8 i;
    for(i=0;i<75;i++);
    }
    通过实测相同的这一段代码:ST执行该函数的延时时间是7.4us,GD执行该函数的延时时间是5.4us。
    如果客户的应用对时间要求比较严格请不要忽略GD代码执行速度的问题,参数需要做一定的调整。
    案例2:
    客户采用IO模拟I2C他的查应答函数的编写如下
    #define SDA_Status() GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) Void CheckACK(void)
    {
    cAcknowledge=TRUE if(SDA_Status())
    {
    cAcknowledge=FalSE;
    }
    }
    客户反馈这段代码在ST上面执行OK,但是在GD上面运行不正常,其实这是由于GD的执行速度更快, ACK信号还出来,语句就已经执行完成了。建议客户修改代码:
    #define SDA_Status()        GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)
    Void        CheckACK(void)
    {
    u8 ErrTimer=0; cAcknowledge=TRUE
    while(SDA_Status())
    {
    ucErrTime++;
    if(ucErrTime>250)
    {
    cAcknowledge=FalSE;
    }
    }
    }
    代码修改后客户的问题得以解决,使用ST没有问题是因为ST的代码执行速度没有GD的快,刚好客 户的代码能满足他的应用,换了GD以后由于代码执行速度更快,只能通过更严谨的逻辑来进行代码 的移植。
    2.1.3 BOOT管脚注意事项
    BOOT0及BOOT1管脚在芯片复位时的电平状态决定了复位后从哪个区域开始执行程序。典型情况下,BOOT0需外接10K下拉电阻,就可 以从Flash启动。如BOOT0悬空,则不能从Flash启动。
    2.2.1 PA8和低功耗关系
    PA8管脚如果外接上拉电阻,会导致在standby模式下有较大的漏电流,会增加standby模式下的功耗, 但是对stop模式下的功耗无影响。因此如果要获得比较低的功耗。PA8 管脚要保持悬空或者是下拉,或者在进 入standby模式之前,断开PA8 管脚与外部的连接。
    2.3定时器方面的说明
    有客户反馈使用GD的MCU,用定时器工作在正交编码或者是输入捕获不能工作,同一程序ST的工作 正常。检查客户的程序,发现客户编程的时候没有配置定时器的周期,而ST的定时器不配置定时器的周期的话 会给出一个默认值,GD不会。在程序中加上配置定时器周期的语句就OK了。
    TIM_TimeBaseStructure.TIM_Period = 0xffff;
    TIM_TimeBaseStructure.TIM_Prescaler =0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
    2.4        ADC方面的说明
    2.4.1        ADC输入通道模式配置
    使用GD的MCU的时候,输入通道必须配制成模拟输入的模式GPIO_Mode_AIN,配制成其他模式不能正 常工作。
    2.4.2 ADC时钟配置问题
    使用GD的MCU的时候,需要ADC的采样配置时钟而且不能大于14M Hz。采样周期配置如下:
    RCC_ADCCLKConfig(RCC_PCLK2_Divx);
    2.4.3 ADC输入阻抗和采样周期选择
    从ST移植到GD,使用到ADC的话需要根据具体情况相应的修改采样周期。具体参数见下表:
    2.5        RTC方面的说明
    GD的RTC正常使用起来和ST的没有差别,但是客户使用的过程中经常会在设计硬件的时候增加一个电阻 或者是不加电容等问题,所以关于RTC方面的设计请严格参照下面的原理图:
    2.6        SPI方面的说明
    2.6.1        CLK线重复配置
    有客户反馈当SPI处于主模式下,重复配置SPI的CLK线会引起内部计数器紊乱:
    问题代码: GPIO->CRL&=0x000fffff;
                      GPIO->CRL|=0xBBB00000;
    上面这段代码是执行SPI口的IO初始化,调用两次后会使CLK上面产生一个脉冲。引起内部计数器出错,ST的 在SPI再次初始化的时候会将内部计数器清零,GD不会将内部计数器清零。
    修改办法: vu32 temp; temp=GPIOA->CFL; temp&=0x000fffff; temp|=0xbbb00000; GPIOA->CRL=temp;
    先进行运算再去进行赋值,内部的SPI 计数器就不会因为CLK数据的变化引起误操作。
    2.6.2 SPI 通信BSY标志位
    在SPI程序编写的过程中,轮询使用BSY作为检测标志位,传送数据丢失或者是错误。这是因为GD的BSY 标志位不是在写入DR后就置位的,而是有很小的一个延时后才置起的。传输过程中不要使用BSY作为每次传 输的判断,使用TXE和 RXNE来进行判断。
    2.6.3 SPI 控制寄存器1(SPI_CR1)配置流程
    客户如果从低到高一位一位配置该寄存器会出现MODF的错误,经过排查是由于GD的MCU在SPE使能之 前就开始检测是否有模式错误,而ST是在SPE使能之后,所以在MSTR写1之前要保证模式正确。SSM为0时 保证外接高电平或者SSM和SSI都写1或者是把SSOE打开。130\150没有该问题.
    案例:BIDIMODE=0; RXONLY=0;MSTR=1;DFF=0;CPOL=0;CPHA=0;SSM=1; SSOE=1;TXEIE=1;BR=2;LSBFIRST=0;CRCPOLY=7;SPE=1;
    这个顺序在ST上正常,在GD上出现MODF错误,解决的话可以将整个寄存器一次写入,也可调整初始化顺 序,同时加上SSI的配置。
    2.7        I2C方面的说明
    2.7.1        查询法I2C寻址判断
    在使用I2C编程的时候需要修改固件库stm32f10x_i2c.h中的两个宏定义
    #define        I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED ((uint32_t)0x00060082)
    #define        I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ((uint32_t)0x00070082)
    修改为:
    #define        I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED ((uint32_t)0x00060002)
    #define        I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED        ((uint32_t)0x00070002)
    2.7.2 函数I2C_CheckEvent修改
    使用V3.5.0之前的固件库需要修改I2C_CheckEvent函数。
    修改前:
    ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
    {
    uint32_t lastevent = 0; uint32_t flag1 = 0, flag2 = 0; ErrorStatus status = ERROR;
    /* Check the parameters */ assert_param(IS_I2C_ALL_PERIPH(I2Cx)); assert_param(IS_I2C_EVENT(I2C_EVENT));
    /* Read the I2Cx status register */ flag1 = I2Cx->SR1;
    flag2 = I2Cx->SR2; flag2 = flag2 << 16;
    /* Get the last event value from I2C status register */ lastevent = (flag1 | flag2) & FLAG_Mask;
    /* Check whether the last event contains the I2C_EVENT */ if (lastevent == I2C_EVENT)
    {
    /* SUCCESS: last event is equal to I2C_EVENT */ status = SUCCESS;
    }
    else
    {
    /* ERROR: last event is different from I2C_EVENT */ status = ERROR;
    }
    /* Return status */ return status;
    }
    修改后:
    ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
    {
    uint32_t lastevent = 0; uint32_t flag1 = 0, flag2 = 0; ErrorStatus status = ERROR;
    /* Check the parameters */ assert_param(IS_I2C_ALL_PERIPH(I2Cx)); assert_param(IS_I2C_EVENT(I2C_EVENT));
    /* Read the I2Cx status register */ flag1 = I2Cx->SR1;
    flag2 = I2Cx->SR2; flag2 = flag2 << 16;
    /* Get the last event value from I2C status register */ lastevent = (flag1 | flag2) & FLAG_Mask;
    /* Check whether the last event contains the I2C_EVENT */ if ((lastevent & I2C_EVENT) == I2C_EVENT)
    {
    /* SUCCESS: last event is equal to I2C_EVENT */ status = SUCCESS;
    }
    else
    {
    /* ERROR: last event is different from I2C_EVENT */ status = ERROR;
    }
    /* Return status */ return status;
    }
    2.8        USART方面的说明
    2.8.1        USART连续发送数据问题
    GD的MCU和ST的相比在连续发送的时候会多一个IDLE bit。对于客户的应用基本没有影响,只是会影响 连续发送的时候的发送时间。
    2.8.2 USART停止位问题  
                GD32的USART发送的时候只发送1 bit或2bit停止位,如果配制成0.5bit则发送1bit。如果配制成1.5bit则发送2bit停止位。  2.9 Flash方面的说明  
        2.9.1 Flash操作修改要点  
       GD的Flash执行速度快,但是写操作慢,所以在对Flash操作的时候需要修改下面几个函数:  
                              FLASH_Status FLASH_EraseOptionBytes(void);  
                              FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);  
                              FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages);  
                              FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState);  
                      在这四个函数写完key  (  FLASH->OPTKEYR = FLASH_KEY1;FLASH->OPTKEYR = FLASH_KEY2; )  
         后添加两个__nop()语句或者是增加   
                          While( ! (FLASH->CR & 0x200 ) );// Wait OPTWRE   
            语句来增加等待的时间。同时修改擦出和写的超时宏定义:  
                  #define EraseTimeout ((uint32_t)0x000B0000)  
                  #define ProgramTimeout((uint32_t)0x00002000)  
              修改为:         
                #define EraseTimeout ((uint32_t)0x000FFFFF)  
                #define ProgramTimeout((uint32_t)0x0000FFFF)  
        2.9.2  Flash起始地址  
    当写操作是,必须采用绝对地址,也就是0x08000000为首地址。而对于读操作,也可以用0x00000000  作为首地址去读  main flash  
        2.9.3  Flash速度  
            HD容量以上芯片  ,>256K  以上Flash的速度很慢. 需要手动调整链接脚本,让对速度敏感的数据、代码的链接地址位于256K前,对于ARM-MDK来说,就是编辑.sct分散加载文件   
    2.10 USB方面的说明  
          有最低工作频率的要求,也就是APB1分频后的时钟必须大于12MHz,比如HCLK为56MHz,APB1 的最大分频系数为4,56/4 = 14MHz,可以正常工作。软件编写的时候要保证USB设置的时钟大于12M。



    回复

    使用道具 举报

    7

    主题

    0

    好友

    152

    积分

    童生

    Rank: 2

  • TA的每日心情
    开心
    2016-5-12 15:06
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2016-5-16 16:11:51 |显示全部楼层
    采样周期表
    123.png

    回复

    使用道具 举报

    7

    主题

    0

    好友

    152

    积分

    童生

    Rank: 2

  • TA的每日心情
    开心
    2016-5-12 15:06
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2016-5-16 16:13:24 |显示全部楼层
    RTC硬件原理图
    456.png

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    关闭

    站长推荐上一条 /6 下一条


    手机版|爱板网 |网站地图  

    GMT+8, 2016-12-6 02:43 , Processed in 0.097252 second(s), 12 queries , Memcache On.

    苏公网安备 32059002001056号

    Powered by Discuz!

    回顶部