关于GD32替换STM32(pin to pin)搭载rt-thread操作系统,需要注意的问题总结

1、SystemInit()函数

该函数位于启动文件中的Reset_Handler中(具体实现在GD32位于system_gd32f4xx.c,STM32位于system_stm32f4xx.c中,几乎所有的文件,你只要把gd换成st就能找到对应的文件),gd的叫startup_gd32Fxxx.s,一般st的也是类似的名字,像startup_st32Fxxx.s,(其实就是兆芯抄的别人的。。)xxx是对应的芯片的具体型号,例如我用的gd32f450,stm32f427的芯片,二者可以pin to pin互换。
两款芯片,在该函数中都是做了reset操作,例如重置向量表,rcc时钟,失能中断等等,两者不同的是gd的函数中多了一个system_clock_config()函数,
需要将该函数注释掉,否则,STM32的对应芯片会起不来,main函数进不去,初始化失败,相反的,如果用ST替换GD,那么一般不需要特别的在此处增加该函数(但需要在其他地方增加类似的函数)。

2、system_clock 系统时钟

上面一节提到了system_clock_config(),该函数就是用来配置系统时钟的,例如如果你定义了
defined (__SYSTEM_CLOCK_168M_PLL_25M_HXTAL)
即使用外部25m时钟源做时钟,通过PLL倍频到168M系统时钟。
然后调用了system_clock_168m_25m_hxtal();函数,该函数即是通过设置rcc的相关寄存器将系统时钟倍频到168M,AHB做1分频,也是168M,APB1做4分频即42M,APB2做2分频即84M, 注意,第一点不同! GD32F4系列产品对应的主频和STM32F4系列芯片主频不同!
GD32F4系列产品的AHB 、 APB2、APB1 域的最高时率分别为 240MHz/120MHz/60MHz,而STM32F4系列的最高主频是AHB 域的最大频率为 168MHz/84MHz/42MHz!所以,我们需要将两者替换的时候,需要注意系统时钟的配置项。一般用GD替换ST的时候,GD可以正常运行,而用ST替换GD的时候,ST不能正常运行的原因就在这里,低主频即使无法完美发挥GD芯片的性能,但是却可以运行,很多人说ST的程序可以直接在GD上跑,反过来不行,就觉得ST的芯片做的好,国产的垃圾,其实并非如此。
第一节,说到替换的时候需要注释掉system_clock_config()函数,我们可以将系统时钟初始化的部分放到main函数开始,或者如果使用了rtt系统可以放到board.cvoid rt_hw_board_init()函数当中;
如果使用SMT32hal库来初始化,那么代码就如下所示:

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  __PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, 5);

  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

前面的

 __PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

是关于PMU的时钟处理,设置调节器输出电压级别以及开启 Over-Driver 功能都是电源控制相关配置,这里的配置直接影响系统时钟的频率,
PWR控制寄存器 CR 的位 15:14 来确定的:
位 15:14 VOS[1:0]
00:保留(默认模式 3 选中)
01:级别 3:HCLK 最大频率 120MHz
10:级别 2: HCLK 最大频率 144MHz
11:级别 1:HCLK 最大频率 168MHz
通过开启 Over-drive 模式可以达到 180MHz(超频模式)
我们如果设置到了168M,那么PWR寄存器我们需要设置为11级别1,即PWR_REGULATOR_VOLTAGE_SCALE1
另外一个需要注意的是FLASH的延时配置,即HAL_RCC_ClockConfig(&RCC_ClkInitStruct, 5);,的参数2;具体的是根据参考手册中的下表来确定的:
在这里插入图片描述
我们的电压是3.3,主频即HCLK168M,所以,我们的等待周期是5WS

3、嵌入式SRAM

关于SRAM,STM32F4系列和GD32F4系列很大不同!通过参考手册(下载链接:STM32F4xxv中文参考手册)我们可以看到:
STM32F4xx:
STM32F4xx
GD32F4xx(下载链接:GD32F4xx中文参考手册):
在这里插入图片描述
STM32SRAM要小一些,特别是GD32有了附加SRAM以后,可以被AHB访问的SRAM可能超过了512KB,而STM32仅有192kb而已。所以位于启动文件中的堆大小即

Stack_Size      EQU     0x00001200

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp


; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Heap_Size       EQU     0x00001200

可能需要根据需要修改。
另外,如果搭载了rt-thread操作系统,位于board.c文件中的关于系统堆大小初始化的地方也需要修改;即函数void rt_hw_board_init()中的rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);函数,
直接根据具体的使用情况修改#define GD32_SRAM_SIZE 128位于board.h当中,我这里修改为了128k的sram。

4、其他的外设的时钟修改

由于两者的主频不一样,所以,一些外设的时钟也需要相应的作出修改,例如IIC IIS,ADC,CAN等外设。
仅以CAN的时钟配置为例,
GD32的标准库中有关于CAN设备的初始化库函数:

//can的mq初始化
rt_mq_init(&gMqRx_CAN0, "MqRxCAN0", gRxCAN0_MsgPool, RxCan0_MsgMaxSize, MsgPoolSize_0, RT_IPC_FLAG_FIFO);
//时钟使能
rcu_periph_clock_enable(RCU_CAN0);
rcu_periph_clock_enable(RCU_GPIOA);
//gpio复用    
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11);//CAN0_RX
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_af_set(GPIOA, GPIO_AF_9, GPIO_PIN_11);
        
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);//CAN0_TX
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_af_set(GPIOA, GPIO_AF_9, GPIO_PIN_12);
//can中断使能
nvic_irq_enable(CAN0_RX0_IRQn, 0, 0);

can_parameter_struct can_parameter; 
can_filter_parameter_struct can_filter;

//can时钟重置使能
rcu_periph_reset_enable(RCU_CAN0RST);
rcu_periph_reset_disable(RCU_CAN0RST);
        
/* initialize CAN parameters */
can_parameter.time_triggered = DISABLE;
can_parameter.auto_bus_off_recovery = DISABLE;
can_parameter.auto_wake_up = DISABLE;
can_parameter.auto_retrans = ENABLE;
can_parameter.rec_fifo_overwrite = DISABLE;
can_parameter.trans_fifo_order = DISABLE;

can_parameter.working_mode = CAN_NORMAL_MODE;
can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
can_parameter.time_segment_1 = CAN_BT_BS1_12TQ;
can_parameter.time_segment_2 = CAN_BT_BS2_8TQ;
        
/* baudrate = 1M, APB1总线*/
can_parameter.prescaler = 2;
can_init(CAN0, &can_parameter);

通过时钟的使能函数或者参考手册,我们可以得知can是挂载在AHB1上的,如果我们设置的时钟系统,AHB142M(即PLL168M,系统时钟168MAHB284M),那么如果将can的波特率设置为1M,我们只需要关注time_segment_1 、time_segment_2 、prescaler 这三个参数即可,can波特率的计算公式为:
在这里插入图片描述
time_segment_1在ST中也被简写成TS1,TS2,prescaler 简写成BRP,都是一样的意思。简化一下,can的波特率公式:

can波特率=AHB1频率/[(TS1+TS2+1)*BRP]

注意公式中的TS1TS2不是实际值,而是几倍的tq的值,例如我们上面程序中的

can_parameter.time_segment_1 = CAN_BT_BS1_12TQ;
can_parameter.time_segment_2 = CAN_BT_BS2_8TQ;

TS1对应是12被的TQTS2对应的是8倍的TQ,但是如果我们查找定义就会发现CAN_BT_BS1_12TQ其实值是11CAN_BT_BS2_8TQ的值是7,如果我们以实际值来算就需要加上2,这里很多博客里面都讲的不明白或者讲错了。
根据公式,我们得到can的波特率=42m/[(8+12+1)*2]=1m,

如果STM32代码中使用标准库或者HAL库,你可以看到都是类似的配置。
至此,我们完成GD32F450替换STM32F427的芯片。

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蒙蒂锅巴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值