平台配置:
开发板:NUCLEO-F746ZG,MCU为STM32F746ZG
库版本:最新版的HAL驱动库
操作系统:liteOS 1.0
第一步、创建裸机工程,工程结构如下图所示
工程目录说明:
app:用户创建的文件都可以添加到这里。
bsp:板级支持文件。
cmsis:架构相关文件
config:配置文件都可以添加到这里
hal:官方cube_hal库
linker:链接文件
startup:启动文件
创建完工程后,编译,改错,确保没有编译错误,有开发板的话最好是写个简单的LED程序测试一下,工程是否可以正常工作,避免移植操作系统时不成功,造成调试困难。
第二步、添加【liteos】源文件到工程中
首先,在工程中添加liteos/arch目录,并添加以下文件到工程,如下图
接着,在工程中添加 liteos/kernel目录,并添加以下文件到工程
los_init.c
base/core
下面全部 .c 文件base/ipc
下面全部 .c 文件base/mem/bestfit_little
下面全部 .c 文件base/mem/common
下面全部 .c 文件base/mem/membox
下面全部 .c 文件base/misc
下面全部 .c 文件base/om
下面全部 .c 文件extended/tickless
下面全部 .c 文件(如果没有使用 tickless,可以不必添加)
接着,在工程添加 liteos/os_config目录,添加以下三个文件方便修改
修改target_config.h
修改成对应MCU系列的头文件
修改为 NO
配置SRAM的起始地址和结束地址
第三步、添加路径,如下图
到这一步,我们可以编译一下试试,发现两个错误,如下图
提示,PendSV_Handler 和 SysTick_Handler重复定义,很简单,注释掉stm32f7xx_it.c中这两个函数,重新编译,没有错误了。
liteos中的 PendSV_Handler 在 los_dispatch_iar.S 中定义
SysTick_Handler 在 los_hwi.c中定义
void SysTick_Handler(void)
{
if (g_bSysTickStart)
{
osTickHandler();
}
else
{
g_ullTickCount++;
//HAL_IncTick(); // 有强迫症的同学可以把这句代码移到这里
}
}
最后,重写一下 HAL_GetTick()函数,这样可以保证HAL_Delay() 函数可以继续正确使用
/* 重写 HAL_GetTick 函数 */
uint32_t HAL_GetTick(void)
{
return (uint32_t)LOS_TickCountGet();
}
重新编译,看有没有错误,完美,没有错误。
第四步、测试移植的正确性
首先,不添加任务,跑裸机LED闪烁工程试试,看能否正常工作,这次改用HAL_Delay()延时,顺便验证一下重写后的HAL_GetTick 函数正常不
main.c 源文件
#include "stm32f7xx.h"
#include "stm32f7xx_nucleo_144.h"
#include "sys_init.h"
#include "dwt.h"
__IO FlagStatus SwitchClock = RESET;
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
HAL_Init();
/* Enable HSI oscillator and configure the PLL to reach the max system frequency (216 MHz)
when using HSI oscillator as PLL clock source. */
SystemClock_Config();
dwt_init(SystemCoreClock);
/* Configure LED1 */
BSP_LED_Init(LED1);
/* Initialize User push-button, will be used to trigger an interrupt each time it's pressed.*/
BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_EXTI);
/* Toggle some leds in an infinite loop */
while (1)
{
/* Toggle LED1 */
BSP_LED_Toggle(LED1);
HAL_Delay(100);
// delayms(100);
}
}
/**
* @brief EXTI line detection callbacks.
* @param GPIO_Pin: Specifies the pins connected EXTI line
* @retval None
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == KEY_BUTTON_PIN)
{
SwitchClock = SET;
}
}
重新编译,下载,很好,程序工作正常。
接下来,使用 liteos 创建一个 LED 闪烁程序,来测试 liteos 内核工作是否正常
先新建一个 includes.h 头文件,然后把所有 liteos 的头文件全部 #include “los_*.h” 到这个文件里,方便以后使用
includes.h 头文件
#ifndef INCLUDES_H
#define INCLUDES_H
#include "los_builddef.h"
#include "los_printf.h"
#include "target_config.h"
#include "los_base.h"
#include "los_compiler.h"
#include "los_config.h"
#include "los_err.h"
#include "los_errno.h"
#include "los_event.h"
#include "los_heap.h"
#include "los_list.h"
#include "los_membox.h"
#include "los_memcheck.h"
#include "los_memory.h"
#include "los_mux.h"
#include "los_queue.h"
#include "los_sem.h"
#include "los_slab.h"
#include "los_swtmr.h"
#include "los_sys.h"
#include "los_task.h"
#include "los_tick.h"
#include "los_tickless.h"
#include "los_typedef.h"
#endif
liteos 内核初始化流程
初始化内核(调用LOS_KernelInit() )---> 创建用户任务 ---> 启动内核(调用 LOS_Start()),简单吧,详细代码如下
liteos初始化过程源代码
// 初始化 liteos
UINT32 uwRet = LOS_OK;
uwRet = LOS_KernelInit();
if(uwRet != LOS_OK)
return LOS_NOK;
//创建用户任务
uwRet = CreatAppTask();
if(uwRet != LOS_OK)
return LOS_NOK;
// 启动 liteos 内核
(void)LOS_Start();
创建 user_task.h 和 user_task.c 文件,源码如下
user_task.h 头文件
#ifndef USER_TASK_H
#define USER_TASK_H
#include "includes.h"
UINT32 CreatAppTask(void);
#endif
user_task.c 源文件
#include "user_task.h"
#include "includes.h"
#include "stm32f7xx_nucleo_144.h"
/*********** task ID ***************************/
UINT32 g_tskLedHandle;
UINT32 g_tskRedHandle;
/* private fn ********************************/
static void Task_LED(void);
static void Task_Red(void);
UINT32 CreatAppTask(void)
{
UINT32 uwRet = LOS_OK;
TSK_INIT_PARAM_S task_init_param;
// 创建第一个任务 Task_LED
task_init_param.usTaskPrio = 2;
task_init_param.pcName = "Task Led";
task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)Task_LED;
task_init_param.uwStackSize = 0x400;
uwRet = LOS_TaskCreate(&g_tskLedHandle,&task_init_param);
if(LOS_OK != uwRet)
return uwRet;
// 创建第二个任务 Task_Red
task_init_param.usTaskPrio = 3;
task_init_param.pcName = "Task Red";
task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)Task_Red;
task_init_param.uwStackSize = 0x400;
uwRet = LOS_TaskCreate(&g_tskRedHandle,&task_init_param);
if(LOS_OK != uwRet)
return uwRet;
return uwRet;
}
// 第一个任务,绿灯闪烁任务
static void Task_LED(void)
{
while(1)
{
BSP_LED_Toggle(LED1);
LOS_TaskDelay(500);
}
}
// 第二个任务,红灯闪烁任务
static void Task_Red(void)
{
while(1)
{
BSP_LED_Toggle(LED3);
LOS_TaskDelay(200);
}
}
编译,下载,go,绿灯和红灯都按照延时要求正确闪烁,说明移植成功了。