Clion+STM32CubeMx开发环境下移植uCos III

1、准备工作

        STM32开发板,我这里用的是STM32F103C8T6,各位小伙伴可以自行选择

        Clion平台下的STM32开发环境,Clion的版本我的是2021.3.4,这个问题不大

        uCos III 的源码,可以区官网自行下载,也可以用我准备好的,连接如下:

链接:https://pan.baidu.com/s/17cegS4sAAlm4LpjyH31J4w 
提取码:7788

         到这里准备工作就搞定了,下面开始创建基础工程,我们将在此工程的基础上移植uCos III

2、基础工程

打开CubeMx选择自己的目标芯片,我的是STM32F103C8T6

 配置用于测试工程所需外部硬件,我这里是使用的LED以及串口,多嘴一句,LED的话无所谓,串口建议还是要开启。

 然后再根据自己的芯片信号配置好晶振以及时钟分频就好了,这里就不演示了,生成工程后,测试一下工程有没有问题(一般都不会有问题),到这里就成功一半了,我就拿串口来做演示

printf( "Hello uC/os III\r\n" );
HAL_Delay( 1000 );

 

 工程配置好了以后,就开始摘取我们所需要的 uCos III 的源码,也就是CV一下,具体看图吧!

3、源码的移植

首先创建如下文件夹

我们一个一个来,双击打开 uC_bsp 文件夹,创建两个文件,一个是 bsp_os.c 以及 bsp_os.h,如图

 打开这两个文件夹将一下代码复制并粘贴到你自己创建的文件下

bsp_os.c

// bsp.c
#include "includes.h"
#include "usart.h"

#define  DWT_CR      *(CPU_REG32 *)0xE0001000
#define  DWT_CYCCNT  *(CPU_REG32 *)0xE0001004
#define  DEM_CR      *(CPU_REG32 *)0xE000EDFC
#define  DBGMCU_CR   *(CPU_REG32 *)0xE0042004

#define  DEM_CR_TRCENA                   (1 << 24)
#define  DWT_CR_CYCCNTENA                (1 <<  0)

CPU_INT32U  BSP_CPU_ClkFreq (void)
{
  return HAL_RCC_GetHCLKFreq();
}

void BSP_Tick_Init(void)
{
  CPU_INT32U cpu_clk_freq;
  CPU_INT32U cnts;
  cpu_clk_freq = BSP_CPU_ClkFreq(  );

#if ( OS_VERSION >= 3000u )
  cnts = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz;
#else
  cnts = cpu_clk_freq / (CPU_INT32U)OS_TICKS_PER_SEC;
#endif
  OS_CPU_SysTickInit( cnts );
}


int _write(int fd, char *ptr, int len)
{
  HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, 0xFFFF);
  return len;
}

int __io_putchar(int ch)
{
  uint8_t temp[1]={ch};
  HAL_UART_Transmit(&huart1,temp,1,0xff);
  return (ch);
}

void BSP_Init(void)
{
  BSP_Tick_Init();
}

#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
/**
 * @brief 初始化事件戳
 * @param NONE
 * @date 2023-11-17
 */
void  CPU_TS_TmrInit (void)
{
  CPU_INT32U  cpu_clk_freq_hz;

  DEM_CR         |= (CPU_INT32U)DEM_CR_TRCENA;                /* Enable Cortex-M3's DWT CYCCNT reg.                   */
  DWT_CYCCNT      = (CPU_INT32U)0u;
  DWT_CR         |= (CPU_INT32U)DWT_CR_CYCCNTENA;

  cpu_clk_freq_hz = BSP_CPU_ClkFreq();
  CPU_TS_TmrFreqSet(cpu_clk_freq_hz);
}/* CPU_TS_TmrInit */
#endif

#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
/**
 * @brief 读取当前时间戳
 * @param NONE
 * @return DWT_CYCCNT寄存器的值
 * @date 2023-11-17
 */
CPU_TS_TMR  CPU_TS_TmrRd (void)
{
  return ( (CPU_TS_TMR)DWT_CYCCNT );
}/* CPU_TS_TmrRd */
#endif

/* Configure CPU timestamp features (see Note #1) :     */
#if (CPU_CFG_TS_32_EN == DEF_ENABLED)
/**
 * @brief uSec延时函数 ( 32bit )
 * @param ts_cnts 延时时间 ( 32bit )
 * @return
 * @date 2023-11-17
 */
CPU_INT64U  CPU_TS32_to_uSec (CPU_TS32  ts_cnts)
{
  CPU_INT64U  ts_us;
  CPU_INT64U  fclk_freq;

  fclk_freq = BSP_CPU_ClkFreq(  );
  ts_us     = ts_cnts / ( fclk_freq / DEF_TIME_NBR_uS_PER_SEC );

  return ( ts_us );
}/* CPU_TS32_to_uSec */
#endif
#if (CPU_CFG_TS_64_EN == DEF_ENABLED)
/**
 * @brief uSec延时函数 ( 64bit )
 * @param ts_cnts 延时时间 ( 64bit )
 * @return
 * @date 2023-11-17
 */
CPU_INT64U  CPU_TS64_to_uSec (CPU_TS64  ts_cnts)
{
	CPU_INT64U  ts_us;
	CPU_INT64U  fclk_freq;

  fclk_freq = BSP_CPU_ClkFreq(  );
  ts_us     = ts_cnts / ( fclk_freq / DEF_TIME_NBR_uS_PER_SEC );

  return (ts_us);
}/* CPU_TS64_to_uSec */
#endif


bsp_os.h 

// bsp.h
#ifndef  __BSP_H__
#define  __BSP_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stm32f1xx_hal.h"

#include "bsp_led.h"
#include "bsp_i2c.h"
#include "bsp_list.h"
/* USER CODE END Includes */

/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */

/* USER CODE END ET */

/* Exported functions prototypes ---------------------------------------------*/
/* USER CODE BEGIN EFP */
void BSP_Init(void);

/* USER CODE END EFP */

#ifdef __cplusplus
}
#endif

#endif /* __BSP_H__ */

 在bsp_os.c/.h中主要实现了 内核微妙延时以及串口的重定向,其他的先不管,接着往下走

打开 uC_cfg 文件夹,然后在uCos III的源码中找到以下文件复制并粘贴,如图

以下是 uC_cpu 文件夹的内容,注意 ARM-Cortex-M3 文件夹内只保留 GNU 文件及其内容,其他的全部删除,这是重点。

 然后打开 uC_lib 文件夹接着复制粘贴,看图吧,同样的 <Ports->ARM-Cortex-M3>目录下,只保留 GNU 文件夹其他的全部删掉,这里就不贴图了

 最后就是 uC_os3 文件夹了,如下图

 这里是 Source 文件夹下的内容,与前面一样,<Ports->ARM-Cortex-M3->Generic>路径下只保留 GNU 文件夹,其他的全部删除

 到这里文件就准备好了,下面开始移植

4、移植 uCos III

 将文件复制到工程文件夹内,各位小伙伴可以像我一向,如图!

包含路径 ,打开 CMakeLists.txt 文件,跟我一样的话可以直接复制过去,代码在下面

include_directories(
        User/include
        User/uCos_III/uC_bsp/include
        User/uCos_III/uC_cfg
        User/uCos_III/uC_cpu
        User/uCos_III/uC_cpu/ARM-Cortex-M3/GNU
        User/uCos_III/uC_lib
        User/uCos_III/uC_lib/Ports/ARM-Cortex-M3/GNU
        User/uCos_III/uC_os3/Source
        User/uCos_III/uC_os3/Ports/ARM-Cortex-M3/Generic/GNU
)

file(GLOB_RECURSE SOURCES "Core/*.*" "Drivers/*.*" "User/*.*")

然后使用 CMake 重新构建项目,并编译(点击 Reload Cmake Projrct)

 此时编译因该是没有错误的

 到这儿就差不多了,对工程做一些简单的更改就可以了,一个是改启动文件,一定不要忘记,不然 系统是无法运行的,找到启动文件,看图吧

 做如下更改

  .word OS_CPU_PendSVHandler
  .word OS_CPU_SysTickHandler




  .weak OS_CPU_PendSVHandler
  .thumb_set OS_CPU_PendSVHandler,Default_Handler

  .weak OS_CPU_SysTickHandler
  .thumb_set OS_CPU_SysTickHandler,Default_Handler

搞定以后就可以测试 uCos III 是否移植成功了在工程下创建  appliance.c/.h 两个文件复制代码

appliance.c

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "includes.h"
#include "appliance.h"

/* USER CODE END Includes */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define START_TASK_PRIO		3     /* 起始任务的任务优先级 */
#define LED1_TASK_PRIO		4     /* LED1任务的任务优先级 */

#define START_STK_SIZE 		96    /* 起始任务的任务堆栈大小 */
#define LED1_STK_SIZE 		96    /* LED1任务的任务堆栈大小 */

/* USER CODE END PD */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */

CPU_STK START_TASK_STK[ START_STK_SIZE ];   /* 起始任务,任务堆栈 */
CPU_STK LED1_TASK_STK[ LED1_STK_SIZE ];     /* LED1任务,任务堆栈 */

OS_TCB StartTaskTCB;                        /* 起始任务,任务控制块实例化 */
OS_TCB Led1TaskTCB;                         /* Led1任务,任务控制块实例化 */

OS_TMR BntScanTime;                         /* 软件定时器实例化 */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
void start_task( void *p_arg );                                 /* 起始任务函数 */
static void led_pa3( void *p_arg );                             /* LED1任务函数 */
static void BtnScanTime_CallBack( void *p_tmr, void *p_arg );   /* 软件定时器回调函数 */

/* USER CODE END PFP */

/**
 * @brief 应用层入口
 * @param None
 * @date 2023-11-16
 */
void Appliance( void )
{
  OS_ERR  err;                                                                /* 声明错误代码存储变量 */
  OSInit(&err);                                                               /* 初始化 uC/OS */

  CPU_SR_ALLOC();                                                             /* 创建临界区变量 */
  OS_CRITICAL_ENTER(  );                                                      /* 进入临界区 */
  OSTaskCreate( (OS_TCB*       ) &StartTaskTCB,                               /* 任务控制块 */
                (CPU_CHAR*     ) "start task",                                /* 任务名 */
                (OS_TASK_PTR   ) start_task,                                  /* 任务函数 */
                (void*         ) NULL,                                        /* 任务函数的入口参数 */
                (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,                                           /* 消息数量 */
                (OS_TICK	     ) 0,                                           /* 时间片数量 */
                (void*         ) NULL,                                        /* 任务 TCB 内存拓展 */
                (OS_OPT        ) (OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR),   /* 创建任务时的附加操作 */
                (OS_ERR*       ) &err);                                       /* 返回错信息 */

  OSTmrCreate( (OS_TMR*              ) &BntScanTime,                          /* 软件定时器控制块 */
               (CPU_CHAR*            ) "BtnScanTime",                         /* 软件定时器的名字 */
               (OS_TICK              ) 5,                                     /* 软件定时器的初始值 */
               (OS_TICK              ) 5,                                     /* 软件定时器的重装载值 */
               (OS_OPT               ) OS_OPT_TMR_PERIODIC,                   /* 软件定时器的工作模式 */
               (OS_TMR_CALLBACK_PTR  ) BtnScanTime_CallBack,                  /* 软件定时器的回调函数 */
               (void*                ) NULL,                                  /* 软件定时器的入口传入参数 */
               (OS_ERR*              ) &err );                                /* 返回错误信息 */
  OS_CRITICAL_EXIT(  );                                                       /* 退出临界区 */
  OSTmrStart( (OS_TMR*) &BntScanTime, (OS_ERR*) &err );                       /* 启动软件定时器 */
  OSStart( &err );                                                            /* 启动任务调度 */
}/* Appliance */

/**
 * @brief 起始任务
 * @param p_arg
 * @date 2023-11-16
 */
void start_task( void *p_arg )
{
  OS_ERR err;
  (void)p_arg;
  CPU_SR_ALLOC(  );                   /* 创建临界区变量 */

  BSP_Init(  );                       /* Initialize BSP functions */
  #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  		/* 当使用时间片轮转的时候 */
    /* 使能时间片轮转调度功能,时间片长度为 1 个系统时钟节拍,既 1 * 5 = 5ms */
    OSSchedRoundRobinCfg( DEF_ENABLED, 1, &err );
  #endif
  OS_CRITICAL_ENTER(  );                                                      /* 进入临界区 */
  OSTaskCreate( (OS_TCB*       ) &Led1TaskTCB,                                /* 任务控制块 */
                (CPU_CHAR*     ) "led_pa3",                                   /* 任务名 */
                (OS_TASK_PTR   ) led_pa3,                                     /* 任务函数 */
                (void*         ) NULL,                                        /* 任务函数的入口参数 */
                (OS_PRIO	     ) LED1_TASK_PRIO,                              /* 任务优先级 */
                (CPU_STK*      ) &LED1_TASK_STK[ 0 ],                         /* 任务堆栈基地址 */
                (CPU_STK_SIZE  ) LED1_STK_SIZE/10,                            /* 任务堆栈溢出最大值 */
                (CPU_STK_SIZE  ) LED1_STK_SIZE,                               /* 任务堆栈大小 */
                (OS_MSG_QTY    ) 0,                                           /* 消息数量 */
                (OS_TICK	     ) 0,                                           /* 时间片数量 */
                (void*         ) NULL,                                        /* 任务 TCB 内存拓展 */
                (OS_OPT        ) (OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR),   /* 创建任务时的附加操作 */
                (OS_ERR*       ) &err);                                       /* 返回错误码 */
  OS_CRITICAL_EXIT(  );                                                       /* 退出临界区 */
  OSTaskDel( (OS_TCB*) &StartTaskTCB, &err );                                 /* 删除起始任务 */
}/* start_task */


void MyPrintf( Data *pTemp )
{
  printf( "%d\r\n", pTemp->Num );
}


/**
 * @brief Led闪烁任务
 * @param p_arg
 * @date 2023-11-16
 */
static void led_pa3 ( void *p_arg )
{
  OS_ERR err;                                                   /* 声明错误代码存储变量 */
  Led_Typedef LED_G = { GPIOB, GPIO_PIN_8, 0 };                 /* 注册一个LED灯 */
  (void)p_arg;                                                  /* 消除编译器警告 */
  BSP_Init(  );                                                 /* Initialize BSP functions                           */
  CPU_Init(  );                                                 /* Initialize CPU module                              */

#if OS_CFG_STAT_TASK_EN > 0u                                    /* 统计任务是否使能                                     */
  OSStatTaskCPUUsageInit( &err );                               /* Compute CPU capacity with no task running          */
#endif

  while ( DEF_TRUE )
  {
    LED.Flips( &LED_G );                                        /* 翻转LED灯 */
    OSTimeDly( 100, OS_OPT_TIME_DLY, &err );                    /* 延时500个时钟节拍 */
  }
}/* led_pa3 */

/**
 * @brief 按键扫描软件定时器回调函数
 * @param p_tmr
 * @param p_arg
 * @date 2023-11-16
 */
static void BtnScanTime_CallBack( void *p_tmr, void *p_arg )
{
  (void)p_arg; (void)p_tmr;
  HAL_GPIO_TogglePin( GPIOA, GPIO_PIN_1 );
}/* BtnScanTime_CallBack */

 appliance.h


#ifndef __APPLIANCE_H__
#define __APPLIANCE_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "includes.h"

/* USER CODE END Includes */

/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */

/* USER CODE END ET */

/* Exported functions prototypes ---------------------------------------------*/
/* USER CODE BEGIN EFP */
void Appliance( void );

/* USER CODE END EFP */

#ifdef __cplusplus
}
#endif

#endif /* __APPLIANCE_H__ */

在主函数中添加一下代码,要记住声明头文件,大伙自行调用吧,这里就不贴代码了

其中有部分代码无关乎移植,删除就可以了,如下

    
void MyPrintf( Data *pTemp )
{
  printf( "%d\r\n", pTemp->Num );
}


Led_Typedef LED_G = { GPIOB, GPIO_PIN_8, 0 };                 /* 注册一个LED灯 */



LED.Flips( &LED_G );                                        /* 翻转LED灯 */

到这里就移植完了,添加测试代码,查看验证就可以了,找到  led_pa3 函数在主循环中添加代码

  while ( DEF_TRUE )
  {
    LED.Flips( &LED_G );                                        /* 翻转LED灯 */
    printf( "Task ---> Run\r\n" );
    OSTimeDly( 100, OS_OPT_TIME_DLY, &err );                    /* 延时500个时钟节拍 */
  }

找到  BtnScanTime_CallBack 函数,添加一下代码

/**
 * @brief 按键扫描软件定时器回调函数
 * @param p_tmr
 * @param p_arg
 * @date 2023-11-16
 */
static void BtnScanTime_CallBack( void *p_tmr, void *p_arg )
{
  (void)p_arg; (void)p_tmr;
  printf( "BtnScanTime ---> Run\r\n" );
}/* BtnScanTime_CallBack */

下载验证就可以了,到此移植完成,结果就不贴图了,反正可看不出来,有问题评论区见吧,告辞

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值