最近淘到一块板子,板载GD32F130C8T6。Cortex-M3内核,64KBFalsh,8KBSRAM。最近正在看FreeRTOS,就拿它来练练手。
一、下载GD库文件
习惯了用STM32,对GD3.1.0的库用着真不习惯,下了1.0.1的库。百度GD32F1x0_Firmware_Library即可。里边有三个文件夹,Examples是一些外设的使用例程,Firmware包含内核文件和库文件,Template里只有一个官方的工程。
打开例程,比较粗糙,所有的外设都包含进去了,编译比较慢,对SYSTICK使用得也比较糙。
重新建了一个工程,对着原子的重新吧systick写了一遍,用着比较舒服。
static u8 fac_us=0; //us延时倍乘数
static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个节拍的ms数
void delay_init()
{
SysTick_CKSource_Enable(SYSTICK_CKSOURCE_HCLK_DIV8);
fac_us=SystemCoreClock/8000000;
fac_ms=(u16)fac_us*1000;
}
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
} while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
} while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
工程包含如下:
因为我这块板子上的晶振是16M的,所以还需要修改以下两个地方,8M的不需要改。
(1)、将gd32f1x0.h的HSE_VALUE改为16000000
(2)、修改system_gd32f1x0.c的 static void Set_SysClockTo72(void)
二、下载FreeRTOS源文件
在其官网FreeRTOS官网点击下载,不用注册,很方便。最新版本是v10.3.1。我用的是v10.2.1的
打开文件,里面两个文件夹,FreeRTOS和FreeRTOS-Plus。FreeRTOS-Plus是一些拓展功能,我们用不到,打开FreeRTOS文件夹,里面三个文件夹,Demo一些移植好的例程,License许可证书,Source源文件。
三、移植
1、 在我们的工程文件下新建一个FreeRTOS文件夹,将FreeRTOS源文件里的Source内容拷贝过来,
——>
其中portable只保留MemMang和RVDS,其余可以删除。
2、打开工程,在里面添加两个文件夹,将源文件添加进去
3、添加头文件路径
4、修改systick
#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"
static u8 fac_us=0; //us延时倍乘数
static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个节拍的ms数
extern void xPortSysTickHandler(void);
void SysTick_Handler(void)
{
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
{
xPortSysTickHandler();
}
}
void delay_init()
{
u32 reload;
SysTick_CKSource_Enable(SYSTICK_CKSOURCE_HCLK);
NVIC_SetPriority(SysTick_IRQn, 0x00);
fac_us=SystemCoreClock/1000000; //每us需要计的数
reload=SystemCoreClock/1000000; //每S需要计的数
reload*=1000000/configTICK_RATE_HZ; //根据configTICK_RATE_HZ设定溢出时间
fac_ms=1000/configTICK_RATE_HZ;
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断
SysTick->LOAD=reload; //每1/configTICK_RATE_HZ秒中断一次
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
}
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD; //LOAD的值
ticks=nus*fac_us;
told=SysTick->VAL; //刚进入时的计数器值
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.
}
}
}
void delay_ms(u32 nms)
{
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
{
if(nms>=fac_ms) //延时的时间大于OS的最少时间周期
{
vTaskDelay(nms/fac_ms); //FreeRTOS延时
}
nms%=fac_ms; //OS已经无法提供这么小的延时了,采用普通方式延时
}
delay_us((u32)(nms*1000)); //普通方式延时
}
//延时nms,不会引起任务调度
void delay_xms(u32 nms)
{
u32 i;
for(i=0; i<nms; i++) delay_us(1000);
}
5、添加FreeRTOSconfig.h
在FreeRTOS源文件的DEMO文件夹中找到CORTEX_STM32F103_Keil将里面的FreeRTOSConfig.h复制到我们工程FreeRTOS\include里
6、添加宏定义
在FreeRTOSConfig.h添加如下宏定义,第一次因为没有这两个宏定义,结果编译通过了,却没有现象。
#define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler
7、修改堆栈大小
在FreeRTOSConfig.h设置RTOS堆栈大小的宏定义,GD32F130C8T6的SRAM只有8KB,所以不能设置太大,否则编译出错。
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 5 * 1024 ) )
8、修改中断设置
在FreeRTOSConfig.h修改中断优先级配置
//------------------中断配置-----------------------------------
#define configPRIO_BITS 4
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 //最低优先级,STM32优先级分组为4,优先级数就是16个,最低优先级那就是15
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )//设置内核中断优先级
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 //高于5的优先级(优先级数小于5)不归 FreeRTOS 管理
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY<<(8 - configPRIO_BITS) )
在main中将中断分组设为4
9、在gd32F1x0_it.c中屏蔽以下三个函数
创建测试任务,编译正常,现象正常
移植好的的工程下载地址:GD32F130-FreeRTOS