基于C++的多任务应用代码框架

0 评论
/
18 阅读
/
15530 字
28 2025-01

项目结构

project/
├── arch/
│   ├── arch_stm32.cpp      // STM32 的上下文切换实现
│   ├── arch_stm32.hpp      // STM32 的硬件抽象层接口
│   ├── arch_pc.cpp         // PC 的上下文切换实现
│   ├── arch_pc.hpp         // PC 的硬件抽象层接口
│   └── arch.hpp            // 硬件抽象层通用接口
├── hal/
│   ├── hal_stm32.cpp       // STM32 的 HAL 实现
│   ├── hal_stm32.hpp       // STM32 的 HAL 接口
│   ├── hal_pc.cpp          // PC 的 HAL 实现
│   ├── hal_pc.hpp          // PC 的 HAL 接口
│   └── hal.hpp             // HAL 通用接口
├── drivers/
│   ├── uart/               // 串口驱动
│   │   ├── uart_stm32.cpp  // STM32 串口驱动
│   │   ├── uart_pc.cpp     // PC 串口驱动
│   │   └── uart.hpp        // 串口驱动接口
│   ├── display/            // 显示驱动
│   │   ├── display_8080.cpp // 8080 接口显示驱动
│   │   ├── display_rgb.cpp  // RGB 接口显示驱动
│   │   ├── display_mipi.cpp // MIPI 接口显示驱动
│   │   ├── display_vbe.cpp  // BIOS VBE3.0 显示驱动
│   │   ├── display_uefi.cpp // UEFI 图形显示驱动
│   │   └── display.hpp      // 显示驱动接口
│   ├── audio/              // 声音驱动
│   │   ├── audio_stm32.cpp // STM32 声音驱动
│   │   ├── audio_pc.cpp    // PC 声音驱动
│   │   └── audio.hpp       // 声音驱动接口
│   ├── input/              // 输入设备驱动
│   │   ├── keyboard.cpp    // 键盘驱动
│   │   ├── mouse.cpp       // 鼠标驱动
│   │   └── input.hpp       // 输入设备驱动接口
│   └── drivers.hpp         // 驱动模块通用接口
├── scheduler/
│   ├── scheduler.cpp       // 任务调度器实现
│   └── scheduler.hpp       // 任务调度器接口
├── tasks/
│   ├── task_led.cpp        // LED 任务实现
│   ├── task_button.cpp     // 按钮任务实现
│   └── tasks.hpp           // 任务函数声明
├── task_manager/
│   ├── task_manager.cpp    // 任务管理器实现
│   └── task_manager.hpp    // 任务管理器接口
├── task_base/
│   ├── task_base.cpp       // 任务基类实现
│   └── task_base.hpp       // 任务基类接口
└── main.cpp                // 主程序
#include "arch.h"
#include "stm32f1xx_hal.h"

// 保存和恢复上下文的汇编代码
__asm void arch_context_switch(uint32_t** current_stack, uint32_t* next_stack) {
    // 保存当前任务的上下文
    PUSH {R4-R11}          // 保存寄存器
    STR SP, [R0]           // 保存当前堆栈指针

    // 切换到下一个任务的上下文
    LDR SP, [R1]           // 加载下一个任务的堆栈指针
    POP {R4-R11}           // 恢复寄存器
    BX LR                  // 返回
}

arch.hpp(硬件抽象层接口)


#ifndef ARCH_HPP
#define ARCH_HPP

#include <cstdint>

class Arch {
public:
    // 上下文切换函数
    static void contextSwitch(uint32_t** currentStack, uint32_t* nextStack);

    // 初始化硬件相关功能
    static void init();
};

#endif // ARCH_HPP

arch_stm32.cpp(STM32 的上下文切换实现)


#include "arch.hpp"
#include "stm32f1xx_hal.h"

// 保存和恢复上下文的汇编代码
extern "C" void arch_context_switch(uint32_t** currentStack, uint32_t* nextStack);

void Arch::contextSwitch(uint32_t** currentStack, uint32_t* nextStack) {
    arch_context_switch(currentStack, nextStack);
}

void Arch::init() {
    HAL_Init();
    SystemClock_Config();
}

hal.hpp(HAL 接口)


#ifndef HAL_HPP
#define HAL_HPP

class HAL {
public:
    // 初始化 GPIO
    static void init();

    // 切换 GPIO 状态
    static void togglePin(int pin);
};

#endif // HAL_HPP

hal_stm32.cpp(STM32 的 HAL 实现)


#include "hal.hpp"
#include "stm32f1xx_hal.h"

void HAL::init() {
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void HAL::togglePin(int pin) {
    if (pin == 5) {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
    } else if (pin == 0) {
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
    }
}

scheduler.hpp(任务调度器接口)

#ifndef SCHEDULER_HPP
#define SCHEDULER_HPP

#include <cstdint>
#include <functional>

class Scheduler {
public:
    // 任务函数类型
    using TaskFunction = std::function<void()>;

    // 添加任务
    static void addTask(TaskFunction taskFunc);

    // 启动调度器
    static void start();

private:
    // 任务结构体
    struct Task {
        TaskFunction taskFunction; // 任务函数
        uint32_t* stackPointer;    // 任务堆栈指针
        uint32_t stack[64];        // 任务堆栈
    };

    static const int MAX_TASKS = 3;
    static Task taskQueue[MAX_TASKS];
    static int currentTaskIndex;
};

#endif // SCHEDULER_HPP

scheduler.cpp(任务调度器实现)


#include "scheduler.hpp"
#include "arch.hpp"

Scheduler::Task Scheduler::taskQueue[Scheduler::MAX_TASKS];
int Scheduler::currentTaskIndex = -1;

void Scheduler::addTask(TaskFunction taskFunc) {
    static int taskCount = 0;
    if (taskCount < MAX_TASKS) {
        taskQueue[taskCount].taskFunction = taskFunc;
        taskQueue[taskCount].stackPointer = taskQueue[taskCount].stack + 63; // 初始化堆栈指针
        taskCount++;
    }
}

void Scheduler::start() {
    if (currentTaskIndex == -1) {
        currentTaskIndex = 0;
        taskQueue[currentTaskIndex].taskFunction();
    }
}

extern "C" void SysTick_Handler(void) {
    HAL_IncTick(); // 更新 HAL 库的 tick

    // 任务切换
    if (Scheduler::currentTaskIndex != -1) {
        int nextTaskIndex = (Scheduler::currentTaskIndex + 1) % Scheduler::MAX_TASKS;
        Arch::contextSwitch(&Scheduler::taskQueue[Scheduler::currentTaskIndex].stackPointer,
                            Scheduler::taskQueue[nextTaskIndex].stackPointer);
        Scheduler::currentTaskIndex = nextTaskIndex;
    }
}

上下文切换(PC 版)


// arch_pc.hpp
#ifndef ARCH_PC_HPP
#define ARCH_PC_HPP

#include <cstdint>
#include <csetjmp>

class Arch {
public:
    // 上下文切换函数
    static void contextSwitch(uint32_t** currentStack, uint32_t* nextStack);

    // 初始化硬件相关功能
    static void init();
};

#endif // ARCH_PC_HPP

// arch_pc.cpp
#include "arch_pc.hpp"
#include <iostream>

void Arch::contextSwitch(uint32_t** currentStack, uint32_t* nextStack) {
    // 使用 setjmp/longjmp 实现上下文切换
    static jmp_buf env;
    if (setjmp(env) == 0) {
        // 保存当前上下文
        *currentStack = reinterpret_cast<uint32_t*>(&env);
        // 切换到下一个上下文
        longjmp(env, 1);
    }
}

void Arch::init() {
    std::cout << "Arch initialized for PC." << std::endl;
}

定时器(PC 版)


// hal_pc.hpp
#ifndef HAL_PC_HPP
#define HAL_PC_HPP

#include <chrono>
#include <thread>

class HAL {
public:
    // 初始化 GPIO
    static void init();

    // 切换 GPIO 状态
    static void togglePin(int pin);

    // 延时函数
    static void delay(uint32_t ms);
};

#endif // HAL_PC_HPP

// hal_pc.cpp
#include "hal_pc.hpp"
#include <iostream>

void HAL::init() {
    std::cout << "HAL initialized for PC." << std::endl;
}

void HAL::togglePin(int pin) {
    std::cout << "Toggling pin " << pin << std::endl;
}

void HAL::delay(uint32_t ms) {
    std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}

任务实现(PC 版)


// task_led.cpp
#include "task_base.hpp"
#include "hal_pc.hpp"

class TaskLed : public TaskBase {
public:
    TaskLed() : TaskBase(taskFunction, 128, 1) {}

private:
    static void taskFunction() {
        while (true) {
            HAL::togglePin(5); // 切换 LED 状态
            HAL::delay(500);   // 延时 500ms
        }
    }
};

// 静态对象,自动注册任务
static TaskLed taskLed;

// task_button.cpp
#include "task_base.hpp"
#include "hal_pc.hpp"

class TaskButton : public TaskBase {
public:
    TaskButton() : TaskBase(taskFunction, 128, 2) {}

private:
    static void taskFunction() {
        while (true) {
            HAL::togglePin(0); // 切换另一个 LED 状态
            HAL::delay(100);   // 延时 100ms
        }
    }
};

// 静态对象,自动注册任务
static TaskButton taskButton;

调度器(PC 版)

调度器的实现与之前相同,直接从任务管理器中获取任务并调度。


// scheduler.hpp
#ifndef SCHEDULER_HPP
#define SCHEDULER_HPP

#include "task_manager.hpp"

class Scheduler {
public:
    static void start();
};

#endif // SCHEDULER_HPP


// scheduler.cpp
#include "scheduler.hpp"
#include "arch_pc.hpp"

void Scheduler::start() {
    const auto& tasks = TaskManager::getTasks();
    if (tasks.empty()) {
        return; // 没有任务
    }

    while (true) {
        for (const auto& task : tasks) {
            task(); // 执行任务
        }
    }
}

arch.hpp(硬件抽象层通用接口)


#ifndef ARCH_HPP
#define ARCH_HPP

#include <cstdint>

class Arch {
public:
    // 上下文切换函数
    static void contextSwitch(uint32_t** currentStack, uint32_t* nextStack);

    // 初始化硬件相关功能
    static void init();
};

#endif // ARCH_HPP

hal.hpp(HAL 通用接口)


#ifndef HAL_HPP
#define HAL_HPP

class HAL {
public:
    // 初始化 GPIO
    static void init();

    // 切换 GPIO 状态
    static void togglePin(int pin);

    // 延时函数
    static void delay(uint32_t ms);
};

#endif // HAL_HPP

scheduler.hpp(调度器接口)


#ifndef SCHEDULER_HPP
#define SCHEDULER_HPP

class Scheduler {
public:
    static void start();
};

#endif // SCHEDULER_HPP

task_manager.hpp(任务管理器接口)


#ifndef TASK_MANAGER_HPP
#define TASK_MANAGER_HPP

#include <vector>
#include <functional>

class TaskManager {
public:
    using TaskFunction = std::function<void()>;

    // 添加任务
    static void addTask(TaskFunction taskFunc, size_t stackSize = 128, int priority = 1);

    // 获取所有任务
    static const std::vector<TaskFunction>& getTasks();

private:
    static std::vector<TaskFunction> tasks; // 任务列表
};

#endif // TASK_MANAGER_HPP

task_base.hpp(任务基类接口)


#ifndef TASK_BASE_HPP
#define TASK_BASE_HPP

#include "task_manager.hpp"

class TaskBase {
public:
    TaskBase(TaskManager::TaskFunction taskFunc, size_t stackSize = 128, int priority = 1);
};

#endif // TASK_BASE_HPP

驱动模块设计

串口驱动(UART)

接口:


// drivers/uart/uart.hpp
#ifndef UART_HPP
#define UART_HPP

class UART {
public:
    static void init(uint32_t baudRate);
    static void send(const uint8_t* data, size_t length);
    static size_t receive(uint8_t* buffer, size_t length);
};

#endif // UART_HPP

STM32 实现:

// drivers/uart/uart_stm32.cpp
#include "uart.hpp"
#include "stm32f1xx_hal.h"

void UART::init(uint32_t baudRate) {
    // 初始化 STM32 的 UART
}

void UART::send(const uint8_t* data, size_t length) {
    // 发送数据
}

size_t UART::receive(uint8_t* buffer, size_t length) {
    // 接收数据
}

PC 实现:


// drivers/uart/uart_pc.cpp
#include "uart.hpp"
#include <iostream>

void UART::init(uint32_t baudRate) {
    std::cout << "UART initialized with baud rate: " << baudRate << std::endl;
}

void UART::send(const uint8_t* data, size_t length) {
    std::cout << "UART send: " << std::string(data, data + length) << std::endl;
}

size_t UART::receive(uint8_t* buffer, size_t length) {
    std::string input;
    std::cin >> input;
    size_t copied = input.copy(reinterpret_cast<char*>(buffer), length);
    return copied;
}

显示驱动(Display)

接口:


// drivers/display/display.hpp
#ifndef DISPLAY_HPP
#define DISPLAY_HPP

class Display {
public:
    static void init();
    static void clear();
    static void drawPixel(int x, int y, uint32_t color);
    static void update();
};

#endif // DISPLAY_HPP

8080 接口实现:


// drivers/display/display_8080.cpp
#include "display.hpp"

void Display::init() {
    // 初始化 8080 接口显示
}

void Display::clear() {
    // 清屏
}

void Display::drawPixel(int x, int y, uint32_t color) {
    // 绘制像素
}

void Display::update() {
    // 更新显示
}

UEFI 图形实现:


// drivers/display/display_uefi.cpp
#include "display.hpp"

void Display::init() {
    // 初始化 UEFI 图形显示
}

void Display::clear() {
    // 清屏
}

void Display::drawPixel(int x, int y, uint32_t color) {
    // 绘制像素
}

void Display::update() {
    // 更新显示
}

声音驱动(Audio)

接口:


// drivers/audio/audio.hpp
#ifndef AUDIO_HPP
#define AUDIO_HPP

class Audio {
public:
    static void init();
    static void play(const uint8_t* data, size_t length);
    static void stop();
};

#endif // AUDIO_HPP

STM32 实现:


// drivers/audio/audio_stm32.cpp
#include "audio.hpp"

void Audio::init() {
    // 初始化 STM32 音频
}

void Audio::play(const uint8_t* data, size_t length) {
    // 播放音频
}

void Audio::stop() {
    // 停止音频
}

PC 实现:


// drivers/audio/audio_pc.cpp
#include "audio.hpp"
#include <iostream>

void Audio::init() {
    std::cout << "Audio initialized." << std::endl;
}

void Audio::play(const uint8_t* data, size_t length) {
    std::cout << "Playing audio..." << std::endl;
}

void Audio::stop() {
    std::cout << "Audio stopped." << std::endl;
}

输入设备驱动(Input)

键盘驱动:


// drivers/input/keyboard.cpp
#include "input.hpp"
#include <iostream>

void Keyboard::init() {
    std::cout << "Keyboard initialized." << std::endl;
}

bool Keyboard::readKey(uint8_t keyCode) {
    // 读取按键状态
    return false;
}

鼠标驱动:


// drivers/input/mouse.cpp
#include "input.hpp"
#include <iostream>

void Mouse::init() {
    std::cout << "Mouse initialized." << std::endl;
}

void Mouse::readPosition(int& x, int& y) {
    // 读取鼠标位置
}

使用示例

主程序


#include "scheduler.hpp"
#include "arch.hpp"
#include "hal.hpp"
#include "drivers/uart/uart.hpp"
#include "drivers/display/display.hpp"
#include "drivers/audio/audio.hpp"
#include "drivers/input/keyboard.hpp"
#include "drivers/input/mouse.hpp"

int main() {
    // 初始化硬件
    Arch::init();
    HAL::init();

    // 初始化驱动
    UART::init(115200);
    Display::init();
    Audio::init();
    Keyboard::init();
    Mouse::init();

    // 启动调度器
    Scheduler::start();

    while (true) {
        // 主循环
    }
}
标签:
    暂无数据