嵌入式轻量级开源操作系统:HeliOS的使用
- 📍项目地址:
https://github.com/heliosproj/HeliOS
- HeliOS项目是一个社区交付的开源项目,用于构建和维护HeliOS嵌入式操作系统(OS)。HeliOS是一个功能齐全的操作系统,旨在满足由爱好者、研究人员、STEM教育工作者和学者组成的广泛用户社区的需求。HeliOS还旨在满足各种技能水平用户的需求,从在其Arduino项目中实施操作系统的电子爱好者,以及到开发将部署到现场的遥感仪器的研究科学家。
- 🎉当前该系统支持的开发环境或平台:
Arduino IDE
、PlatformIO IDE
、ARM Cortex-M
。
✨请注意,当使用ESP32 Arduino内核时,Espressif ESP32微控制器上不支持
HeliOS
。这是因为ESP32 Arduino内核是基于FreeRTOS
构建的,HeliOS
和FreeRTOS
不能在同一个应用程序中共存。要针对ESP32,HeliOS
必须使用Espressif的SDK构建,而不是使用ESP32 Arduino内核。/src/port.h
和/src/port.c
的文件也需要更新必要的代码来控制中断和访问微控制器的滴答计时器。
- 对于微控制器的MMU或MPU(内存保护单元)启用时,可能无法从用户代码中访问内存映射寄存器和I/O。
- 📜
HeliOS
API文档说明:https://github.com/heliosproj/HeliOS/blob/master/doc/HeliOS_Developers_Guide.pdf
-
🔖本文主要测试
Arduino IDE
平台的使用和用Keil MDK以ARM Cortex-M
MCU移植HeliOS
的使用。
📘Arduino IDE平台构建和测试
- 🔧安装依赖库
HeliOS
- 📑库所提供的相关测试例程:
- 📝测试例程代码一:
一个基础的点灯程序。
c
/*UNCRUSTIFY-OFF*/
/**
* @file Blink.ino
* @author Manny Peterson <manny@heliosproj.org>
* @brief An example Arduino sketch
* @version 0.4.1
* @date 2023-03-19
*
* @copyright
* HeliOS Embedded Operating System Copyright (C) 2020-2023 HeliOS Project <license@heliosproj.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
*
*/
/*UNCRUSTIFY-ON*/
#include <Arduino.h>
#include <HeliOS.h>
void blinkTask_main(xTask task_, xTaskParm parm_) {
int ledState = DEREF_TASKPARM(int, parm_);
if(ledState) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("LED colosed");
ledState = 0;
} else {
digitalWrite(LED_BUILTIN, LOW);
Serial.println("LED open");
ledState = 1;
}
DEREF_TASKPARM(int, parm_) = ledState;
return;
}
void setup() {
xTask blink;
int ledState;
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
//初始化系统
if(ERROR(xSystemInit())) {
xSystemHalt();//停止HeliOS
}
//创建一个任务:传入任务指针 task、任务名称 "PRINTTSK"、任务函数 taskPrint_main 和任务函数参数
if(ERROR(xTaskCreate(&blink, (const xByte *) "BLINKTSK", blinkTask_main, &ledState))) {
xSystemHalt();
}
//将任务置于"等待"状态。
if(ERROR(xTaskWait(blink))) {
xSystemHalt();
}
//同步扫描来更改任务计时器的时间间隔周期。任务被调度执行的间隔时间
if(ERROR(xTaskChangePeriod(blink, 1000))) {
xSystemHalt();
}
//启动HeliOS调度程序
if(ERROR(xTaskStartScheduler())) {
xSystemHalt();
}
xSystemHalt();
}
void loop() {
}
- 🔖以上代码,上传到328PB上传测试结果:
- 📝测试例程代码二:
运行两个占用不同时间的任务函数
c
/*UNCRUSTIFY-OFF*/
/**
* @file Coop.ino
* @author Manny Peterson <manny@heliosproj.org>
* @brief An example Arduino sketch
* @version 0.4.1
* @date 2023-03-19
*
* @copyright
* HeliOS Embedded Operating System Copyright (C) 2020-2023 HeliOS Project <license@heliosproj.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
*
*/
/*UNCRUSTIFY-ON*/
#include <Arduino.h>
#include <HeliOS.h>
void taskShort_main(xTask task_, xTaskParm parm_) {
/* Arduino's delay() is only used here to demonstrate HeliOS functionality and
* must not be used in a real application built on HeliOS. */
delay(500);
Serial.print("S");
digitalWrite(LED_BUILTIN, LOW);
}
void taskLong_main(xTask task_, xTaskParm parm_) {
/* Arduino's delay() is only used here to demonstrate HeliOS functionality and
* must not be used in a real application built on HeliOS. */
delay(1000);
Serial.println("L");
digitalWrite(LED_BUILTIN, HIGH);
}
void setup() {
xTask shortTask;
xTask longTask;
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
if(ERROR(xSystemInit())) {
xSystemHalt();
}
if(ERROR(xTaskCreate(&shortTask, (const xByte *) "SHORTTSK", taskShort_main, null))) {
xSystemHalt();
}
if(ERROR(xTaskCreate(&longTask, (const xByte *) "LONGTSK ", taskLong_main, null))) {
xSystemHalt();
}
if(ERROR(xTaskResume(shortTask))) {
xSystemHalt();
}
if(ERROR(xTaskResume(longTask))) {
xSystemHalt();
}
if(ERROR(xTaskStartScheduler())) {
xSystemHalt();
}
xSystemHalt();
}
void loop() {
}
- 📝测试例程代码三:
查询系统和任务信息
c
/*UNCRUSTIFY-OFF*/
/**
* @file GetInfo.ino
* @author Manny Peterson <manny@heliosproj.org>
* @brief An example Arduino sketch
* @version 0.4.1
* @date 2023-03-19
*
* @copyright
* HeliOS Embedded Operating System Copyright (C) 2020-2023 HeliOS Project <license@heliosproj.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
*
*/
/*UNCRUSTIFY-ON*/
#include <Arduino.h>
#include <HeliOS.h>
void taskPrint_main(xTask task_, xTaskParm parm_) {
String str;
xTaskInfo tinfo;
xSystemInfo sinfo;
//用于获取关于单个任务的信息。提供了任务的状态和名称以及任务的运行时统计信息。
if(OK(xTaskGetTaskInfo(task_, &tinfo))) {
str = "taskPrint_main(): id = ";
str += tinfo->id;
str += ", name = ";
str += xByte2String(CONFIG_TASK_NAME_BYTES, tinfo->name);
str += ", state = ";
str += tinfo->state;
str += ", ltime = ";
str += tinfo->lastRunTime;
str += ", ttime = ";
str += tinfo->totalRunTime;
Serial.println(str);
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
//释放堆内存
if(ERROR(xMemFree(tinfo))) {
xSystemHalt();
}
}
//获取系统信息:名称、版本和任务的数量
if(OK(xSystemGetSystemInfo(&sinfo))) {
str = "taskPrint_main(): ";
str += xByte2String(OS_PRODUCT_NAME_SIZE, sinfo->productName);
str += " ";
str += sinfo->majorVersion;
str += ".";
str += sinfo->minorVersion;
str += ".";
str += sinfo->patchVersion;
str += " has ";
str += sinfo->numberOfTasks;
str += " task.";
Serial.println(str);
if(ERROR(xMemFree(sinfo))) {
xSystemHalt();
}
}
}
void setup() {
xTask task;
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
if(ERROR(xSystemInit())) {
xSystemHalt();
}
if(ERROR(xTaskCreate(&task, (const xByte *) "PRINTTSK", taskPrint_main, null))) {
xSystemHalt();
}
if(ERROR(xTaskWait(task))) {
xSystemHalt();
}
if(ERROR(xTaskChangePeriod(task, 1000))) {
xSystemHalt();
}
if(ERROR(xTaskStartScheduler())) {
xSystemHalt();
}
xSystemHalt();
}
void loop() {
}
📗Keil MDK以 ARM Cortex-M
MCU移植HeliOS
的使用
- 🔖这里以常见的
stm32f103
为例,基于STM32CubeMX
生成必要的工程代码作为基础。来实现对HeliOS
系统的移植使用。
📄STM32移植HeliOS
使用步骤
- 🌿使用
STM32CubeMX
创建工程。 - 🔧修改默认时基:由于
HeliOS
需要使用到滴答定时器
作为时基,所以这里换成一个没有使用到的基本定时器。
- 🔨
NVIC
修改,取消默认滴答定时器中断回调代码生成的勾选:由于HeliOS
原驱动代码中已经包含相关代码。
- 🔖其他的外设,可以按需配置即可。
📑移植部分
- 🌿将
HeliOS
原项目下载下来,拷贝项目中src
,文件夹到自己所创建的项目文件夹中。
- 🌿将源文件(.c)添加到工程中:
- 🌿将头文件(.h)路径添加到工程目录中:
- 🌿添加宏
CMSIS_ARCH_CORTEXM
:
- 🔧修改头文件
port.h
:
c
#elif defined(CMSIS_ARCH_CORTEXM)
// #include "stm32f429xx.h"
#include "stm32f1xx_hal.h"//mcu型号头文件
#define DISABLE_INTERRUPTS() __disable_irq()
#define ENABLE_INTERRUPTS() __enable_irq()
// #define SYSTEM_CORE_CLOCK_FREQUENCY 0xF42400u /* 16000000u */
#define SYSTEM_CORE_CLOCK_FREQUENCY 0x44AA200u /* 72000000u 修改主频*/
#define SYSTEM_CORE_CLOCK_PRESCALER 0x3E8u /* 1000u 分频系数*/
- 📝
main.c
,添加必要的HeliOS.h
头文件,创建任务。
c
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "HeliOS.h"
/* USER CODE END Includes */
- 创建任务:
c
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void blinkTask_main(xTask task_, xTaskParm parm_) {
int ledState = DEREF_TASKPARM(int, parm_);
if(ledState) {
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
printf("LED colosed.\r\n");
ledState = 0;
} else {
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
printf("LED open.\r\n");
ledState = 1;
}
DEREF_TASKPARM(int, parm_) = ledState;
return;
}
/* USER CODE END 0 */
- main函数:
c
int main(void)
{
/* USER CODE BEGIN 1 */
xTask blink;
GPIO_PinState ledState;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
if(ERROR(xSystemInit())) {
xSystemHalt();
}
if(ERROR(xTaskCreate(&blink, (const xByte *) "BLINKTSK", blinkTask_main, &ledState))) {
xSystemHalt();
}
if(ERROR(xTaskWait(blink))) {
xSystemHalt();
}
if(ERROR(xTaskChangePeriod(blink, 1000))) {
xSystemHalt();
}
if(ERROR(xTaskStartScheduler())) {
xSystemHalt();
}
xSystemHalt();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
- 驱动代码效果和上面的Arduino代码差不多。
📚移植后的工程测试源码
c
通过网盘分享的文件:HeliOS_Temp.rar
链接: https://pan.baidu.com/s/1PTqbM2gSwFqDfamEW_w-tA?pwd=pmdm 提取码: pmdm