前言
最近打算将FreeRTOS移植到国产芯片GD32H7系列芯片上,记录一下代码移植的过程。
一、操作步骤
1.下载最新的FreeRTOS源码,下载地址如下:
2.下载GD32H7最新的代码工程,官网下载地址如下:
GD32H7最新的代码工程下载地址
也可以下载最新的H7的示例代码,里面有固件包和最新的代码模板。
3.打开KEIL软件进行手动从零创建工程
创建这几个目录:
然后KEIL目录里面实际的显示配置情况是这样的。
4.将我们之前下载的固件包中的CMSIS文件全部拷贝到我们创建的CMSIS文件夹中
5.将RTOS的源码拷贝到我们创建的FreeRTOS目录中,然后只留下如下的几个文件和文件夹:
6.library目录放置我们下载的BSP包,内容如下:
将所有的include和source目录拷贝到我们的library目录下面。
7.创建RTOS的两个目录,freertoscode和freertosport。因为本次我们使用的是GD32H7是使用的m7的内核,所以文件应该添加\FreeRTOS\portable\RVDS\ARM_CM7\r0p1的port.c文件以及FreeRTOS\portable\MemMang\heap4.c文件,做好以上的工作之后,整个工程的目录结构大概是这样的:
8.然后添加头文件的引用路径
之后编译发现报错,然后添加如下文件到这个目录:
9.在gd32h7xx_it.h中将如下几个函数进行屏蔽
#if 0
void SVC_Handler(void)
{
/* if SVC exception occurs, go to infinite loop */
while(1) {
}
}
#endif
/*!
\brief this function handles PendSV exception
\param[in] none
\param[out] none
\retval none
*/
#if 0
void PendSV_Handler(void)
{
/* if PendSV exception occurs, go to infinite loop */
while(1) {
}
}
#endif
/*!
\brief this function handles SysTick exception
\param[in] none
\param[out] none
\retval none
*/
#if 0
void SysTick_Handler(void)
{
delay_decrement();
}
#endif
10.在systick.c文件中将SysTick_Handler函数进行重写
#include "gd32h7xx.h"
#include "systick.h"
#include "FreeRTOS.h"
#include "task.h"
volatile static uint32_t delay;
/*!
\brief configure systick
\param[in] none
\param[out] none
\retval none
*/
void systick_config(void)
{
/* setup systick timer for 1000Hz interrupts */
if(SysTick_Config(SystemCoreClock / 1000U)) {
/* capture error */
while(1) {
}
}
/* configure the systick handler priority */
NVIC_SetPriority(SysTick_IRQn, 0x00U);
}
extern void xPortSysTickHandler(void);
void SysTick_Handler(void){
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)
{
xPortSysTickHandler();
}
}
最后进行编译,发现无错误和无警告,编译通过。
11.然后我们在main.c函数中写一个简单的测试程序验证我们本次的实时操作系统移植工作是否完成,内容如下:
#include "gd32h7xx.h"
#include "gd32h7xx_libopt.h"
#include "systick.h"
#include "FreeRTOS.h"
#include "task.h"
#include "gd32h757z_start.h"
#define START_TASK_PRIO 1
#define START_STK_SIZE 128
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);
#define LED1_TASK_PRIO 3
#define LED1_STK_SIZE 50
TaskHandle_t LED1Task_Handler;
void LED_Thread1(void *pvParameters);
int main(void)
{
systick_config();
rcu_periph_clock_enable(RCU_GPIOC);
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_0);
xTaskCreate((TaskFunction_t )start_task,
(const char* )"start_task",
(uint16_t )START_STK_SIZE,
(void* )NULL,
(UBaseType_t )START_TASK_PRIO,
(TaskHandle_t* )&StartTask_Handler);
vTaskStartScheduler();
}
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
xTaskCreate((TaskFunction_t )LED_Thread1,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
vTaskDelete(StartTask_Handler);
taskEXIT_CRITICAL();
}
void LED_Thread1(void *pvParameters)
{
while(1)
{
gpio_bit_set(GPIOC, GPIO_PIN_0);
vTaskDelay(500);
gpio_bit_reset(GPIOC, GPIO_PIN_0);
vTaskDelay(500);
}
}
12.编译通过,然后下载验证发现LED灯正常亮灭,证明我们本次移植成功。
总结
本次使用KEIL开发工具从零开始搭建工程,然后进行配置工程文件和编译通过,经过下载验证之后,我们的板子的LED灯可以正常亮灭,证明我们使用这种方式移植操作系统也是可行的。