-
下载ucosiii源码
下载链接:ucosiii 3.04 -
GD32F470官网例程
下载链接:GD32F4XX例程 -
移植后工程
下载链接:移植后工程 -
移植讲解
4.1、准备基础工程,(跑马灯实验工程)可通过以上链接下载;
4.2、UCOSIII源码,可通过以上链接下载,打开后有以下4个文件夹;
4.3、EvalBoards文件夹中,红框中文件是需要我们添加到工程中的;
4.4、 uC-CPU文件夹
这个文件里面是与CPU相关的代码,有下面几个文件:
cpu_core.c文件:该文件包含了适用于所有CPU架构的C代码。该文件包含了用来测量中断关闭事件的函数(中断关闭和打开分别由CPU_CRITICAL_ENTER()和CPU_CRITICAL_EXIT()两个宏实现),还包含了一个可模仿前导码零计算的函数(以防止CPU不提供这样的指令),以及一些其他的函数。
cpu_core.h文件:包含cpu_core.c中函数的原型声明,以及用来测量中断关闭时间变量的定义。
cpu_def.h文件:包含uC/CPU模块使用的各种#define常量
ARM-Cortex-M4文件夹:ARM-Cortex-M3文件夹下有三个文件夹:GNU,IAR,RealView,我们使用的是keil MDK编译器,所以只需要看RealView文件夹,RealView文件夹下有3个文件:cpu.h、 cpu_a.asm、 cpu_c.c文件,这3个文件的具体内容如下:
①cpu.h文件:包含了一些类型的定义,使UCOSIII和其他模块可与CPU架构和编译器字宽度无关。在该文件中用户能够找到CPU_INT16U、 CPU_INT32U、 CPU_FP32等数据类型的定义。该文件还指定了CPU使用的是大端模式还是小端模式,定义了UCOSIII使用的 CPU_STK数据类型,定义了CPU_CRITICAL_ENTER()和CPU_CRITICAL_EXTI(),还包括一些与CPU架构相关的函数声明。
②cpu_a.asm文件:该文件包含了一些用汇编语言编写的函数,可用来开中断和关中断,计算前导零(如果CPU支持这条指令),以及其他一些只能用汇编语言编写的与CPU相关的函数,这个文件中的函数可以从C代码中调用。
③cpu_c.c文件:包含了一些基于特定CPU架构但为了可移植而用C语言编写的函数C代码,作为一个普通原则,除非汇编语言能显著提高性能,否则尽量用C语言编写函数。
注意,上面的cpu.h 、cpu_a.asm和cpu_c.c这3个文件,是在uC_CPU文件夹中ARM-Cortex-M4文件夹下的,打开ARM-Cortex-M4文件夹如图所示:
4.5、 uC_LIB文件
uC_LIB是由一些可移植并且与编译器无关的函数组成,UCOSIII不使用uC_LIB中的函数,但是UCOSIII和uC_CPU假定lib_def.h是存在的,uC_LIB包含以下几个文件:lib_ascii.h和lib_ascii.c文件:提供ASCII_ToLower()、ASCII_ToUpper()、ASCII_IsAlpha()和ASCII_IsDig()等函数,他们可以分别替代标准库函数tolower()、toupper()、isalpha()和isdigit()等。
lib_def.h文件:定义了许多常量,如TURE/FALSE、YES/NO、ENABLE/DISABLE,以及各种进制的常量。但是,该文件中所有#define常量都以DEF_打头,所以上述常量的名字实际上为DEF_TRUE/DEF_FALSE等。该文件还为常量数字计算定义了宏。
lib_math.h和lib_math.c文件:包含了Math_Rand()、Math_SetRand()等函数的源代码,可用来替代标准库函数rand()、srand()。
lib_mem.c和lib_mem.h文件:包含了Mem_Clr()、Mem_Set()、Mem_Copy和Mem_Cmp()等函数的源代码,可用于替代标准库函数memclr()、memset()、memcpy()和memcmp()等。
lib_str.c和lib_str.h文件:包含了str_Len()、str_Copy()和str_Cmp()等函数的源代码,可用于替代标准库函数strlen()、strcpy()、ctrcmp()等。
lib_mem_a.asm文件:lib_mem_a.asm文件在Ports->ARM_Cortex-M4->RealView下,包含了lib_mem.c函数的汇编优化版。
4.6、uCOS-III文件
这个文件夹中有2个文件Ports和Source,Ports文件为与CPU平台有关的文件,Source文件夹里面为UCOSIII 3.04的源码,打开Source文件夹如图所示:
5、ucosiii移植
5.1向工程中添加相应的文件
修改启动文件
6、主程序文件代码
#include "gd32f4xx.h"
#include "gd32f470i_eval.h"
#include "systick.h"
#include "delay.h"
#include <stdio.h>
//#include "includes.h"
//任务优先级
#define START_TASK_PRIO 3
//任务堆栈大小
#define START_STK_SIZE 128
//任务控制块
OS_TCB StartTaskTCB;
//任务堆栈
CPU_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *p_arg);
//任务优先级
#define TASK1_TASK_PRIO 4
//任务堆栈大小
#define TASK1_STK_SIZE 128
//任务控制块
OS_TCB Task1_TaskTCB;
//任务堆栈
CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];
void task1_task(void *p_arg);
//任务优先级
#define TASK2_TASK_PRIO 5
//任务堆栈大小
#define TASK2_STK_SIZE 128
//任务控制块
OS_TCB Task2_TaskTCB;
//任务堆栈
CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE];
//任务函数
void task2_task(void *p_arg);
//任务优先级
#define TASK3_TASK_PRIO 6
//任务堆栈大小
#define TASK3_STK_SIZE 128
//任务控制块
OS_TCB Task3_TaskTCB;
//任务堆栈
CPU_STK TASK3_TASK_STK[TASK3_STK_SIZE];
//任务函数
void task3_task(void *p_arg);
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
OS_ERR err;
CPU_SR_ALLOC();
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
systick_config();
/* enable the LEDs GPIO clock */
rcu_periph_clock_enable(RCU_GPIOE);
rcu_periph_clock_enable(RCU_GPIOF);
/* configure LED1 GPIO port */
gpio_mode_set(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
/* reset LED1 GPIO pin */
gpio_bit_set(GPIOE, GPIO_PIN_2);
/* enable the LED2 GPIO clock */
/* configure LED2 GPIO port */
gpio_mode_set(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
/* reset LED2 GPIO pin */
gpio_bit_set(GPIOE, GPIO_PIN_3);
/* enable the LED3 GPIO clock */
/* configure LED3 GPIO port */
gpio_mode_set(GPIOF, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_10);
gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
/* reset LED3 GPIO pin */
gpio_bit_set(GPIOF, GPIO_PIN_10);
OSInit(&err);
OS_CRITICAL_ENTER();//进入临界区
//创建开始任务
OSTaskCreate((OS_TCB * )&StartTaskTCB, //任务控制块
(CPU_CHAR * )"start task", //任务名字
(OS_TASK_PTR )start_task, //任务函数
(void * )0, //传递给任务函数的参数
(OS_PRIO )START_TASK_PRIO, //任务优先级
(CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位
(CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
(OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度,
(void * )0, //用户补充的存储区
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项,为了保险起见,所有任务都保存浮点寄存器的值 |OS_OPT_TASK_SAVE_FP
(OS_ERR * )&err); //存放该函数错误时的返回值
OS_CRITICAL_EXIT(); //退出临界区
OSStart(&err); //开启UCOSIII
while(1);
}
//开始任务任务函数
void start_task(void *p_arg)
{
OS_ERR err;
CPU_SR_ALLOC();
p_arg = p_arg;
CPU_Init();
Mem_Init();
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); //统计任务
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间
CPU_IntDisMeasMaxCurReset();
#endif
#if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候
//使能时间片轮转调度功能,设置默认的时间片长度
OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
#endif
OS_CRITICAL_ENTER(); //进入临界区
//创建TASK1任务
OSTaskCreate((OS_TCB * )&Task1_TaskTCB,
(CPU_CHAR * )"Task1 task",
(OS_TASK_PTR )task1_task,
(void * )0,
(OS_PRIO )TASK1_TASK_PRIO,
(CPU_STK * )&TASK1_TASK_STK[0],
(CPU_STK_SIZE)TASK1_STK_SIZE/10,
(CPU_STK_SIZE)TASK1_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,//|OS_OPT_TASK_SAVE_FP
(OS_ERR * )&err);
//创建TASK2任务
OSTaskCreate((OS_TCB * )&Task2_TaskTCB,
(CPU_CHAR * )"task2 task",
(OS_TASK_PTR )task2_task,
(void * )0,
(OS_PRIO )TASK2_TASK_PRIO,
(CPU_STK * )&TASK2_TASK_STK[0],
(CPU_STK_SIZE)TASK2_STK_SIZE/10,
(CPU_STK_SIZE)TASK2_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,//|OS_OPT_TASK_SAVE_FP
(OS_ERR * )&err);
//创建TASK3任务
OSTaskCreate((OS_TCB * )&Task3_TaskTCB,
(CPU_CHAR * )"task3 task",
(OS_TASK_PTR )task3_task,
(void * )0,
(OS_PRIO )TASK3_TASK_PRIO,
(CPU_STK * )&TASK3_TASK_STK[0],
(CPU_STK_SIZE)TASK3_STK_SIZE/10,
(CPU_STK_SIZE)TASK3_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,//|OS_OPT_TASK_SAVE_FP
(OS_ERR * )&err);
OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err);//挂起开始任务
OS_CRITICAL_EXIT(); //退出临界区
// OSTaskDel((OS_TCB*)0,&err); //删除start_task任务自身
}
//task1任务函数
void task1_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
gpio_bit_toggle(GPIOE, GPIO_PIN_2);
OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
}
}
//task2任务函数
void task2_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
gpio_bit_toggle(GPIOF, GPIO_PIN_10);
OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
}
}
//task3任务函数
void task3_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
gpio_bit_toggle(GPIOE, GPIO_PIN_3);
OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
}
}
7、工程配置
下载器配置成ST-link,直接使用st-link便可以下载和调试。
8、现象
3个led同时闪烁,间隔500ms。