第一部分 MVP框架程序设计

1. 系统启动流程

1.1 主函数 main()

/**
 * @file main.c
 * @brief 系统主入口
 */
​
int main(void)
{
    /* 1. 系统初始化 */
    SystemInit();                    // 时钟、中断配置
    DWT_Init();                      // 性能计数器初始化
    
    /* 2. 静态内存池初始化 */
    static_memory_pool_init();       // 初始化所有静态内存池
    
    /* 3. uCOS-II初始化 */
    OSInit();                        // RTOS内核初始化
    
    /* 4. 创建启动任务 */
    OSTaskCreate(startup_task,       // 任务函数
                 NULL,               // 参数
                 &startup_stack[0],  // 栈地址
                 TASK_STACK_SIZE_MEDIUM,
                 TASK_PRIO_MAIN,    // 优先级3
                 &startup_tcb);      // TCB指针
    
    /* 5. 启动多任务调度 */
    OSStart();                       // 永不返回
    
    return 0;
}

1.2 系统启动流程图

┌─────────────────────────────────────────────────────────────────────┐
│                        系统启动流程                                  │
└─────────────────────────────────────────────────────────────────────┘
​
    [上电复位]
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 1. 硬件初始化 (SystemInit)                                        │
│    ├── 配置系统时钟 168MHz                                         │
│    ├── 初始化中断向量表                                            │
│    ├── 配置FPU(浮点单元)                                         │
│    └── 初始化DWT性能计数器                                         │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 2. 静态内存池初始化 (static_memory_pool_init)                     │
│    ├── 小对象池: 32B × 48 = 1.5KB                                 │
│    ├── 中对象池: 256B × 24 = 6KB                                  │
│    ├── 大对象池: 1KB × 12 = 12KB                                  │
│    ├── DMA池: 2KB × 6 = 12KB (SRAM, 32B对齐)                      │
│    └── 任务栈池: 512B × 20 = 10KB (CCM RAM)                       │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 3. uCOS-II内核初始化 (OSInit)                                     │
│    ├── 初始化任务控制块链表                                        │
│    ├── 初始化事件控制块链表                                        │
│    ├── 创建空闲任务                                                │
│    └── 创建统计任务                                                │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 4. 创建启动任务 (OSTaskCreate)                                    │
│    └── 优先级3,栈大小512字节                                      │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 5. 启动调度器 (OSStart)                                           │
│    └── 开始运行最高优先级就绪任务                                  │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 6. 运行启动任务 (startup_task)                                    │
│    ├── HAL层初始化                                                 │
│    ├── 创建应用任务                                                │
│    └── 删除自身                                                    │
└───────────────────────────────────────────────────────────────────┘

1.3 启动任务函数

/**
 * @brief 启动任务 - 第一个运行的用户任务
 * @param p_arg 任务参数(未使用)
 * 
 * 函数流程:
 * 1. 初始化硬件抽象层
 * 2. 创建应用任务
 * 3. 打印系统信息
 * 4. 删除自身
 */
static void startup_task(void *p_arg)
{
    (void)p_arg;
    
    /* 1. 初始化硬件抽象层 */
    hal_spi_init();      // 初始化SPI1/2/3
    hal_uart_init();     // 初始化USART1/2/3/4/5/6
    hal_adc_init();      // 初始化ADC1/2/3
    
    /* 2. 创建应用任务 */
    task_manager_create("SPI_Task", spi_task, NULL,
                        TASK_PRIO_SPI_DRIVER, TASK_STACK_SIZE_MEDIUM);
    task_manager_create("UART_Task", uart_task, NULL,
                        TASK_PRIO_UART_DRIVER, TASK_STACK_SIZE_MEDIUM);
    task_manager_create("ADC_Task", adc_task, NULL,
                        TASK_PRIO_ADC_DRIVER, TASK_STACK_SIZE_MEDIUM);
    task_manager_create("Presenter", device_presenter_task, NULL,
                        TASK_PRIO_PRESENTER, TASK_STACK_SIZE_LARGE);
    task_manager_create("Monitor", system_monitor_task, NULL,
                        TASK_PRIO_MONITOR, TASK_STACK_SIZE_SMALL);
    
    /* 3. 打印系统信息 */
    printf("\n========== System Ready ==========\n");
    printf("CPU: 168MHz, RTOS: uCOS-II\n");
    printf("Memory: SRAM 112KB, CCM RAM 64KB\n");
    printf("Tasks: %d created\n", task_manager_get_task_count());
    static_pool_print_stats();
    
    /* 4. 删除自身 */
    OSTaskDel(OS_PRIO_SELF);
}

2. 硬件抽象层运行流程

2.1 SPI设备创建与配置流程

/**
 * @brief SPI设备创建函数
 * @param spi_id SPI总线ID (1-3)
 * @return SPI设备指针
 * 
 * 函数流程:
 * 1. 从静态内存池分配设备结构体
 * 2. 初始化函数指针
 * 3. 创建互斥锁
 * 4. 获取BSP句柄
 */
HalSpiDevice_t* hal_spi_create(uint32_t spi_id)
{
    HalSpiDevice_t *dev;
    HalSpiPriv_t *priv;
    
    /* 1. 分配内存(从静态池) */
    dev = (HalSpiDevice_t *)static_pool_alloc(MEM_POOL_SMALL);
    if (dev == NULL) return NULL;
    
    priv = (HalSpiPriv_t *)static_pool_alloc(MEM_POOL_SMALL);
    if (priv == NULL) {
        static_pool_free(dev);
        return NULL;
    }
    
    /* 2. 初始化设备结构体 */
    memset(dev, 0, sizeof(HalSpiDevice_t));
    memset(priv, 0, sizeof(HalSpiPriv_t));
    
    dev->id = spi_id;
    sprintf(dev->name, "spi%d", spi_id);
    dev->open = hal_spi_open;
    dev->close = hal_spi_close;
    dev->config = hal_spi_config;
    dev->transfer = hal_spi_transfer;
    dev->transfer_double_buf = hal_spi_transfer_double_buf;
    dev->priv_data = priv;
    
    /* 3. 创建互斥锁 */
    dev->mutex = OSMutexCreate(0, &err);
    
    /* 4. 获取BSP句柄 */
    priv->bsp_handle = bsp_spi_get_handle(spi_id);
    
    return dev;
}

2.2 SPI配置流程图

┌─────────────────────────────────────────────────────────────────────┐
│                    SPI配置流程 (hal_spi_config)                     │
└─────────────────────────────────────────────────────────────────────┘
​
    [调用] hal_spi_config(dev, &cfg)
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 1. 参数验证                                                       │
│    if (priv == NULL || cfg == NULL) return ERROR;                 │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 2. 临界区保护                                                     │
│    OS_ENTER_CRITICAL();                                           │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 3. 停止当前运行                                                    │
│    if (priv->is_running) {                                        │
│        bsp_spi_stop(priv->bsp_handle);                            │
│        priv->is_running = false;                                  │
│    }                                                              │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 4. 转换配置参数(适配器模式)                                      │
│    bsp_cfg.mode = cfg->mode;                                      │
│    bsp_cfg.baud_rate = cfg->baudRate;                             │
│    bsp_cfg.data_width = cfg->dataWidth;                           │
│    bsp_cfg.cpol = cfg->cpol;                                      │
│    bsp_cfg.cpha = cfg->cpha;                                      │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 5. 调用BSP层配置                                                  │
│    result = bsp_spi_config(priv->bsp_handle, &bsp_cfg);           │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 6. DMA初始化(如果启用)                                          │
│    if (cfg->useDma && priv->dma_tx == NULL) {                     │
│        priv->dma_tx = dma_manager_alloc(DMA_CHANNEL_SPI_TX);      │
│        priv->dma_rx = dma_manager_alloc(DMA_CHANNEL_SPI_RX);      │
│    }                                                              │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 7. 退出临界区                                                     │
│    OS_EXIT_CRITICAL();                                            │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
    [返回] result

2.3 SPI双缓冲DMA传输流程

/**
 * @brief SPI DMA双缓冲传输实现
 * @param dev SPI设备指针
 * @param buf0 缓冲区0
 * @param buf1 缓冲区1
 * @param size 缓冲区大小
 * @param callback 完成回调
 * @return 操作结果
 */
static HalSpiResult_t hal_spi_transfer_double_buf(HalSpiDevice_t *dev,
                                                    uint8_t *buf0,
                                                    uint8_t *buf1,
                                                    uint32_t size,
                                                    void (*callback)(void *arg))
{
    HalSpiPriv_t *priv = (HalSpiPriv_t *)dev->priv_data;
    DmaConfig_t dma_cfg;
    
    /* 1. 创建双缓冲管理器 */
    DoubleBufferConfig_t db_cfg = {
        .buffer_size = size,
        .buffer0_mem = buf0,
        .buffer1_mem = buf1,
        .use_semaphore = true
    };
    priv->double_buffer = double_buffer_create(&db_cfg);
    
    /* 2. 配置DMA接收通道(外设到内存) */
    dma_cfg.src_addr = (uint32_t)&(priv->bsp_handle->regs->DR);
    dma_cfg.dst_addr = (uint32_t)buf0;
    dma_cfg.size = size;
    dma_cfg.src_inc = DMA_ADDR_FIXED;
    dma_cfg.dst_inc = DMA_ADDR_INC;
    dma_cfg.dir = DMA_PERIPH_TO_MEM;
    dma_cfg.complete_callback = spi_dma_callback;
    dma_cfg.callback_arg = dev;
    
    dma_manager_config(priv->dma_rx, &dma_cfg);
    
    /* 3. 配置双缓冲模式 */
    DMA_DoubleBufferModeConfig(priv->dma_rx->channel_num,
                                (uint32_t)buf1,
                                DMA_Memory_0);
    DMA_DoubleBufferCmd(priv->dma_rx->channel_num, ENABLE);
    
    /* 4. 启动DMA */
    dma_manager_start(priv->dma_rx);
    
    /* 5. 使能SPI DMA接收 */
    bsp_spi_dma_enable(priv->bsp_handle, true);
    
    /* 6. 启动SPI硬件 */
    bsp_spi_start(priv->bsp_handle);
    
    return HAL_SPI_OK;
}

3. 双缓冲DMA数据流

3.1 双缓冲数据流图

┌─────────────────────────────────────────────────────────────────────────┐
│                        双缓冲DMA数据流                                   │
└─────────────────────────────────────────────────────────────────────────┘
​
    [SPI硬件寄存器]
          │
          │ 硬件自动传输
          ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │                      DMA控制器                                  │
    │  ┌─────────────────────────────────────────────────────────┐   │
    │  │                    双缓冲模式                           │   │
    │  │                                                         │   │
    │  │   缓冲区0 (2KB)        缓冲区1 (2KB)                   │   │
    │  │   ┌─────────────┐      ┌─────────────┐                 │   │
    │  │   │ 数据填充中  │ ───► │   空闲      │                 │   │
    │  │   └─────────────┘      └─────────────┘                 │   │
    │  │         │                    ▲                         │   │
    │  │         │ 缓冲区满           │                         │   │
    │  │         ▼                    │                         │   │
    │  │   ┌─────────────┐      ┌─────────────┐                 │   │
    │  │   │   已满     │ ───► │ 数据填充中  │                 │   │
    │  │   └─────────────┘      └─────────────┘                 │   │
    │  │         │                    │                         │   │
    │  │         │ 触发中断           │                         │   │
    │  │         ▼                    │                         │   │
    │  └─────────┼────────────────────┼─────────────────────────┘   │
    └────────────┼────────────────────┼─────────────────────────────┘
                 │                    │
                 │ 中断               │
                 ▼                    ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │                      DMA中断服务程序                            │
    │                                                                 │
    │  void DMA2_Stream0_IRQHandler(void)                            │
    │  {                                                             │
    │      OSIntEnter();                                             │
    │      if (DMA_GetFlagStatus(...)) {                             │
    │          DMA_ClearFlag(...);                                   │
    │          double_buffer_switch(db);  // 切换缓冲区              │
    │          OSSemPost(sem_data_ready); // 唤醒任务                │
    │      }                                                         │
    │      OSIntExit();                                              │
    │  }                                                             │
    └─────────────────────────────────────────────────────────────────┘
                 │
                 │ 信号量
                 ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │                    SPI数据处理任务                              │
    │                                                                 │
    │  void spi_task(void *p_arg)                                    │
    │  {                                                             │
    │      while (1) {                                               │
    │          OSSemPend(sem_data_ready, 0);  // 等待数据            │
    │          buf = double_buffer_get_ready(); // 获取就绪缓冲区    │
    │          process_spi_data(buf);          // 处理数据           │
    │          double_buffer_release(buf);     // 释放缓冲区         │
    │      }                                                         │
    │  }                                                             │
    └─────────────────────────────────────────────────────────────────┘

3.2 缓冲区切换状态机

/**
 * @brief 双缓冲切换函数(在DMA中断中调用)
 * @param db 双缓冲管理器指针
 * @return 新的活动缓冲区索引
 */
uint8_t double_buffer_switch(DoubleBuffer_t *db)
{
    uint8_t new_active;
    uint8_t old_active;
    
    /* 进入临界区 */
    OS_ENTER_CRITICAL();
    
    old_active = db->active_buf;
    new_active = (old_active == 0) ? 1 : 0;
    
    /* 状态转换:当前缓冲区从FILLING变为FULL */
    if (old_active == 0) {
        db->state0 = BUF_STATE_FULL;
        db->valid_data_len = db->buffer_size;
    } else {
        db->state1 = BUF_STATE_FULL;
        db->valid_data_len = db->buffer_size;
    }
    
    /* 检查新缓冲区状态 */
    if (new_active == 0) {
        if (db->state0 != BUF_STATE_EMPTY) {
            db->overflow_count++;
            OS_EXIT_CRITICAL();
            return old_active;  // 溢出,不切换
        }
        db->state0 = BUF_STATE_FILLING;
    } else {
        if (db->state1 != BUF_STATE_EMPTY) {
            db->overflow_count++;
            OS_EXIT_CRITICAL();
            return old_active;
        }
        db->state1 = BUF_STATE_FILLING;
    }
    
    db->active_buf = new_active;
    db->switch_count++;
    
    /* 发送信号量唤醒任务 */
    OSSemPost(db->sem_data_ready);
    
    OS_EXIT_CRITICAL();
    
    return new_active;
}

4. 静态内存池管理

4.1 内存池初始化函数

/**
 * @brief 初始化单个内存池
 * @param pool 内存池指针
 * @param data 内存池数据区
 * @param block_size 块大小
 * @param block_count 块数量
 * @return true-成功, false-失败
 */
static bool init_single_pool(StaticPool_t *pool, 
                              uint8_t *data, 
                              uint32_t block_size, 
                              uint32_t block_count)
{
    uint32_t i;
    PoolBlock_t *block;
    
    /* 1. 初始化控制块 */
    pool->pool_start = data;
    pool->block_size = block_size;
    pool->block_count = block_count;
    pool->used_count = 0;
    pool->alloc_count = 0;
    pool->free_count = 0;
    pool->fail_count = 0;
    
    /* 2. 构建空闲链表 */
    pool->free_list = (PoolBlock_t *)data;
    block = pool->free_list;
    
    for (i = 0; i < block_count - 1; i++) {
        block->next = (PoolBlock_t *)(data + (i + 1) * block_size);
        block = block->next;
    }
    block->next = NULL;  /* 最后一个块指向NULL */
    
    /* 3. 创建互斥锁 */
    pool->mutex = OSMutexCreate(0, &err);
    pool->initialized = true;
    
    return true;
}

4.2 内存池分配流程图

┌─────────────────────────────────────────────────────────────────────┐
│                    静态内存池分配流程                                 │
└─────────────────────────────────────────────────────────────────────┘
​
    [调用] static_pool_alloc(MEM_POOL_SMALL)
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 1. 获取互斥锁                                                     │
│    OSMutexPend(pool->mutex, 0);                                   │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 2. 检查空闲链表                                                   │
│    if (pool->free_list == NULL) {                                │
│        pool->fail_count++;                                        │
│        OSMutexPost(pool->mutex);                                  │
│        return NULL;  // 分配失败                                  │
│    }                                                              │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 3. 从链表头取块                                                   │
│    block = pool->free_list;                                       │
│    pool->free_list = block->next;                                 │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 4. 更新统计信息                                                   │
│    pool->used_count++;                                            │
│    pool->alloc_count++;                                           │
│    if (pool->used_count > pool->peak_used) {                      │
│        pool->peak_used = pool->used_count;                        │
│    }                                                              │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 5. 释放互斥锁                                                     │
│    OSMutexPost(pool->mutex);                                      │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
    [返回] (void *)block

4.3 内存池释放函数

/**
 * @brief 释放内存回池
 * @param ptr 内存指针
 * 
 * 函数流程:
 * 1. 根据地址确定所属池
 * 2. 获取互斥锁
 * 3. 将块放回链表头
 * 4. 更新统计
 */
void static_pool_free(void *ptr)
{
    StaticPool_t *pool = NULL;
    PoolBlock_t *block;
    uint32_t addr = (uint32_t)ptr;
    
    /* 1. 确定所属池 */
    for (uint32_t i = 0; i < MEM_POOL_MAX; i++) {
        uint32_t start = (uint32_t)g_pools[i].pool_start;
        uint32_t end = start + g_pools[i].block_size * g_pools[i].block_count;
        
        if (addr >= start && addr < end) {
            pool = &g_pools[i];
            break;
        }
    }
    
    if (pool == NULL) return;
    
    /* 2. 获取互斥锁 */
    OSMutexPend(pool->mutex, 0, &err);
    
    /* 3. 放回链表头 */
    block = (PoolBlock_t *)ptr;
    block->next = pool->free_list;
    pool->free_list = block;
    
    /* 4. 更新统计 */
    pool->used_count--;
    pool->free_count++;
    
    OSMutexPost(pool->mutex);
}

5. MVP架构数据流

5.1 数据模型更新流程

/**
 * @brief SPI数据更新(生产者调用)
 * @param model 数据模型指针
 * @param data SPI传感器数据
 * @return true-成功, false-失败
 */
bool data_model_update_spi(DataModel_t *model, SpiSensorData_t *data)
{
    uint8_t next_idx;
    
    /* 1. 获取互斥锁 */
    OSMutexPend(model->mutex_data, 0, &err);
    
    /* 2. 计算下一个写指针 */
    next_idx = (model->spi_write_idx + 1) % 8;
    
    /* 3. 缓冲区满处理(覆盖最旧数据) */
    if (next_idx == model->spi_read_idx) {
        model->data_drop_count++;
        model->spi_read_idx = (model->spi_read_idx + 1) % 8;
    }
    
    /* 4. 写入数据 */
    memcpy(&model->spi_data[model->spi_write_idx], data, sizeof(SpiSensorData_t));
    model->spi_write_idx = next_idx;
    
    /* 5. 释放互斥锁 */
    OSMutexPost(model->mutex_data);
    
    /* 6. 通知所有观察者 */
    DataObserver_t *obs = model->observers[DATA_TYPE_SPI];
    while (obs != NULL) {
        if (obs->on_data_changed != NULL) {
            obs->on_data_changed(obs, DATA_TYPE_SPI, data, sizeof(SpiSensorData_t));
        }
        obs = obs->next;
    }
    
    /* 7. 发送信号量唤醒消费者 */
    OSSemPost(model->sem_spi_ready);
    
    return true;
}

5.2 MVP数据流图

┌─────────────────────────────────────────────────────────────────────────┐
│                         MVP完整数据流                                   │
└─────────────────────────────────────────────────────────────────────────┘
​
    [硬件中断/DMA]
          │
          │ 原始数据
          ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │                    Model (数据模型)                             │
    │                                                                 │
    │  data_model_update_spi(data)                                   │
    │      │                                                         │
    │      ├── 环形缓冲区写入                                         │
    │      ├── 更新写指针                                             │
    │      └── notify_observers()  ──────────────────────┐           │
    └─────────────────────────────────────────────────────┼───────────┘
                                                          │
                                                          │ 观察者通知
                                                          ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │                  Presenter (数据展示器)                         │
    │                                                                 │
    │  on_spi_data_changed(observer, data)                           │
    │      │                                                         │
    │      ├── 数据校验                                               │
    │      ├── 格式转换                                               │
    │      ├── 告警检查                                               │
    │      └── view->update_display(data)  ─────────────────┐        │
    └───────────────────────────────────────────────────────┼────────┘
                                                            │
                                                            │ 显示更新
                                                            ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │                      View (视图层)                              │
    │                                                                 │
    │  console_update_display(view, type, data)                      │
    │      │                                                         │
    │      ├── printf("SPI Sensor: ID=%u, Data=", sensor_id)         │
    │      ├── for (i=0; i<len; i++) printf("%02X ", data[i])        │
    │      └── printf("\n")                                          │
    └─────────────────────────────────────────────────────────────────┘

5.3 数据观察者注册流程

/**
 * @brief 注册数据观察者
 * @param model 数据模型
 * @param type 数据类型
 * @param observer 观察者指针
 */
void data_model_register_observer(DataModel_t *model, 
                                   DataType_t type, 
                                   DataObserver_t *observer)
{
    OS_ERR err;
    
    if (model == NULL || observer == NULL) {
        return;
    }
    
    /* 获取互斥锁 */
    OSMutexPend(model->mutex_data, 0, &err);
    
    /* 添加到观察者链表头部 */
    observer->next = model->observers[type];
    model->observers[type] = observer;
    
    OSMutexPost(model->mutex_data);
}

6. 任务间通信流程

6.1 消息发送流程

/**
 * @brief 发送消息(异步)
 * @param msg 消息指针
 * @return true-成功, false-失败
 */
bool msg_center_send(SystemMessage_t *msg)
{
    MsgCenter_t *center = msg_center_get_instance();
    OS_ERR err;
    bool result = false;
    
    if (center == NULL || msg == NULL) {
        return false;
    }
    
    /* 1. 获取互斥锁 */
    OSMutexPend(center->mutex_subscriber, 0, &err);
    
    /* 2. 确定目标队列 */
    if (msg->dst_task == 0) {
        /* 广播模式:发送给所有订阅者 */
        Subscriber_t *sub = center->subscribers[msg->type];
        while (sub != NULL) {
            OSQPost(center->task_queues[sub->task_id], msg);
            sub = sub->next;
        }
        result = true;
    } else {
        /* 单播模式:发送给指定任务 */
        if (center->task_queues[msg->dst_task] != NULL) {
            OSQPost(center->task_queues[msg->dst_task], msg);
            result = true;
        }
    }
    
    /* 3. 更新统计 */
    center->total_messages++;
    
    OSMutexPost(center->mutex_subscriber);
    
    return result;
}

6.2 消息接收流程

/**
 * @brief 接收消息(阻塞)
 * @param task_id 任务ID
 * @param timeout 超时时间
 * @return 消息指针
 */
SystemMessage_t* msg_center_receive(uint32_t task_id, uint32_t timeout)
{
    MsgCenter_t *center = msg_center_get_instance();
    SystemMessage_t *msg = NULL;
    OS_ERR err;
    
    if (center == NULL || task_id >= TASK_MAX_NUM) {
        return NULL;
    }
    
    /* 从消息队列接收 */
    msg = (SystemMessage_t *)OSQPend(center->task_queues[task_id], timeout, &err);
    
    return msg;
}

6.3 任务间通信流程图

┌─────────────────────────────────────────────────────────────────────────┐
│                       任务间通信流程                                    │
└─────────────────────────────────────────────────────────────────────────┘
​
    [任务A]
        │
        │ 创建消息
        ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │ msg.type = MSG_TYPE_DATA_READY;                                 │
    │ msg.dst_task = TASK_B_ID;                                       │
    │ msg.data = &data;                                               │
    └─────────────────────────────────────────────────────────────────┘
        │
        │ msg_center_send(&msg)
        ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │                      消息中心                                   │
    │                                                                 │
    │  ┌─────────────────────────────────────────────────────────┐   │
    │  │ 1. 查找目标任务队列                                      │   │
    │  │ 2. 互斥锁保护                                            │   │
    │  │ 3. OSQPost(队列, 消息)                                   │   │
    │  │ 4. 更新统计                                              │   │
    │  └─────────────────────────────────────────────────────────┘   │
    └─────────────────────────────────────────────────────────────────┘
        │
        │ 消息入队
        ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │                 [任务B的消息队列]                               │
    │  ┌─────┐  ┌─────┐  ┌─────┐  ┌─────┐                           │
    │  │ msg1│→│ msg2│→│ msg3│→│ ... │                           │
    │  └─────┘  └─────┘  └─────┘  └─────┘                           │
    └─────────────────────────────────────────────────────────────────┘
        │
        │ OSQPend()
        ▼
    [任务B] 接收并处理消息

7. 中断服务程序流程

7.1 DMA中断处理流程

/**
 * @file stm32f4xx_it.c
 * @brief DMA2 Stream0中断处理(ADC DMA)
 */
void DMA2_Stream0_IRQHandler(void)
{
    /* 1. 进入中断,通知uCOS-II */
    OSIntEnter();
    
    /* 2. 检查传输完成中断标志 */
    if (DMA_GetFlagStatus(DMA2_Stream0, DMA_FLAG_TCIF0) != RESET) {
        /* 3. 清除中断标志 */
        DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_TCIF0);
        
        /* 4. 调用DMA管理器中断处理 */
        dma_manager_irq_handler(DMA2_Stream0);
        
        /* 5. 缓冲区切换(在dma_manager中调用) */
        // double_buffer_switch(db);
        
        /* 6. 发送信号量唤醒任务 */
        // OSSemPost(sem_data_ready);
    }
    
    /* 7. 退出中断,触发任务调度 */
    OSIntExit();
}

7.2 UART中断处理流程

/**
 * @brief USART1中断处理
 */
void USART1_IRQHandler(void)
{
    OSIntEnter();
    
    /* 1. 接收数据寄存器非空中断 */
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        uint8_t data = USART_ReceiveData(USART1);
        
        /* 2. 调用HAL层回调 */
        hal_uart_rx_isr_handler(uart_device[0], data);
        
        /* 3. 写入环形缓冲区 */
        ring_buffer_write(rx_ring, data);
        
        /* 4. 发送信号量 */
        OSSemPost(sem_rx_data);
    }
    
    /* 5. 发送完成中断 */
    if (USART_GetITStatus(USART1, USART_IT_TC) != RESET) {
        USART_ClearITPendingBit(USART1, USART_IT_TC);
        hal_uart_tc_isr_handler(uart_device[0]);
        OSSemPost(sem_tx_complete);
    }
    
    /* 6. 错误中断处理 */
    if (USART_GetITStatus(USART1, USART_IT_ORE) != RESET) {
        USART_ClearITPendingBit(USART1, USART_IT_ORE);
        uart_error_handler(uart_device[0], UART_ERROR_OVERRUN);
    }
    
    OSIntExit();
}

7.3 中断处理流程图

┌─────────────────────────────────────────────────────────────────────────┐
│                      中断处理完整流程                                   │
└─────────────────────────────────────────────────────────────────────────┘
​
    [硬件触发中断]
          │
          ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │ 1. CPU自动压栈                                                  │
    │    - PC, LR, R0-R3, R12, xPSR                                  │
    │    - 进入Handler模式                                            │
    └─────────────────────────────────────────────────────────────────┘
          │
          ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │ 2. 中断向量表跳转                                               │
    │    - 从0x08000000 + 4*IRQn读取向量                              │
    │    - 跳转到中断服务函数                                          │
    └─────────────────────────────────────────────────────────────────┘
          │
          ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │ 3. OSIntEnter() - 通知RTOS                                      │
    │    - OSIntNesting++                                             │
    │    - 禁止任务调度                                                │
    └─────────────────────────────────────────────────────────────────┘
          │
          ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │ 4. 中断处理函数体                                                │
    │    ├── 读取状态寄存器                                           │
    │    ├── 清除中断标志                                             │
    │    ├── 处理数据(最小化)                                        │
    │    ├── 写入环形缓冲区                                            │
    │    └── 发送信号量                                                │
    └─────────────────────────────────────────────────────────────────┘
          │
          ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │ 5. OSIntExit() - 退出RTOS                                       │
    │    - OSIntNesting--                                             │
    │    - if (OSIntNesting == 0) 检查任务调度                        │
    │    - 如果有更高优先级任务就绪,触发PendSV                        │
    └─────────────────────────────────────────────────────────────────┘
          │
          ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │ 6. 中断返回                                                     │
    │    - 出栈恢复现场                                               │
    │    - 返回被中断的任务                                            │
    └─────────────────────────────────────────────────────────────────┘

8. 系统监控与故障恢复

8.1 监控任务完整代码

/**
 * @file monitor_task.c
 * @brief 系统监控任务
 */
void system_monitor_task(void *p_arg)
{
    (void)p_arg;
    
    /* 初始化监控数据 */
    MonitorData_t *monitor = &g_monitor_data;
    monitor->cpu_alarm_threshold = 90;
    monitor->mem_alarm_threshold = 4096;
    
    /* 初始化看门狗 */
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
    IWDG_SetPrescaler(IWDG_Prescaler_64);
    IWDG_SetReload(1250);  // 2秒超时
    IWDG_Enable();
    
    /* 主监控循环 */
    while (1) {
        /* 1. 计算CPU使用率 */
        uint32_t idle_count = OSIdleCtr;
        uint32_t total_count = OSIdleCtrMax;
        
        if (total_count > monitor->total_counter_last) {
            uint32_t idle_delta = idle_count - monitor->idle_counter_last;
            uint32_t total_delta = total_count - monitor->total_counter_last;
            
            if (total_delta > 0) {
                monitor->cpu_usage_percent = 100 - (idle_delta * 100 / total_delta);
                
                /* CPU过载检测 */
                if (monitor->cpu_usage_percent > monitor->cpu_alarm_threshold) {
                    if (!monitor->is_cpu_overload) {
                        monitor->is_cpu_overload = true;
                        SystemMessage_t msg = {
                            .type = MSG_TYPE_ERROR_REPORT,
                            .priority = MSG_PRIO_HIGH,
                            .data = &monitor->cpu_usage_percent
                        };
                        msg_center_send(&msg);
                    }
                } else {
                    monitor->is_cpu_overload = false;
                }
            }
        }
        
        monitor->idle_counter_last = idle_count;
        monitor->total_counter_last = total_count;
        
        /* 2. 检查内存使用 */
        StaticPoolStats_t stats;
        static_pool_get_stats(MEM_POOL_SMALL, &stats);
        
        if (stats.free_blocks < 10) {  // 少于10个空闲块
            if (!monitor->is_memory_low) {
                monitor->is_memory_low = true;
                SystemMessage_t msg = {
                    .type = MSG_TYPE_ERROR_REPORT,
                    .priority = MSG_PRIO_HIGH,
                    .data_len = sizeof(uint32_t),
                    .data = &stats.free_blocks
                };
                msg_center_send(&msg);
            }
        } else {
            monitor->is_memory_low = false;
        }
        
        /* 3. 检查任务看门狗 */
        TaskInfo_t tasks[OS_MAX_TASKS];
        uint32_t task_count = task_manager_get_all_info(tasks, OS_MAX_TASKS);
        
        for (uint32_t i = 0; i < task_count; i++) {
            /* 检查栈溢出 */
            if (tasks[i].stack_used > tasks[i].stack_size - 64) {
                SystemMessage_t msg = {
                    .type = MSG_TYPE_ERROR_REPORT,
                    .priority = MSG_PRIO_HIGH,
                    .data_len = sizeof(uint32_t) * 2,
                };
                msg_center_send(&msg);
            }
        }
        
        /* 4. 更新系统状态到数据模型 */
        DataModel_t *model = data_model_get_instance();
        SystemStatus_t status = {
            .uptime_ms = OSTimeGet(),
            .cpu_usage = monitor->cpu_usage_percent,
            .free_heap = stats.free_blocks * stats.block_size,
            .task_count = task_count
        };
        data_model_update_system(model, &status);
        
        /* 5. 喂看门狗 */
        IWDG_ReloadCounter();
        
        /* 6. 延时100ms */
        OSTimeDlyHMSM(0, 0, 0, 100);
    }
}

8.2 监控任务流程图

┌─────────────────────────────────────────────────────────────────────────┐
│                      系统监控任务流程图                                  │
└─────────────────────────────────────────────────────────────────────────┘
​
    [任务启动]
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 初始化监控数据                                                    │
│ - CPU告警阈值: 90%                                                │
│ - 内存告警阈值: 4KB                                               │
│ - 初始化看门狗: 2秒超时                                           │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
    ┌───────────────────────────────────────────────────────────────┐
    │                    主循环(每100ms)                          │
    └───────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 1. 计算CPU使用率                                                  │
│    ├── 读取空闲任务计数器                                          │
│    ├── 计算使用率 = 100 - (空闲增量/总增量)                        │
│    └── 如果 >90% 发送告警                                          │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 2. 检查内存使用                                                    │
│    ├── 获取静态内存池统计                                          │
│    ├── 如果空闲块 <10 发送告警                                     │
│    └── 更新最小空闲记录                                            │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 3. 检查任务看门狗                                                  │
│    ├── 遍历所有任务                                                │
│    ├── 检查栈使用率 >90% 告警                                      │
│    └── 检查任务是否挂死                                            │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 4. 更新系统状态到数据模型                                          │
│    ├── CPU使用率                                                   │
│    ├── 空闲内存                                                    │
│    └── 任务数量                                                    │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 5. 喂看门狗                                                        │
│    └── IWDG_ReloadCounter()                                       │
└───────────────────────────────────────────────────────────────────┘
        │
        ▼
┌───────────────────────────────────────────────────────────────────┐
│ 6. 延时100ms                                                      │
│    └── OSTimeDlyHMSM(0,0,0,100)                                  │
└───────────────────────────────────────────────────────────────────┘
        │
        └──────────────────→ 返回主循环

9. 完整运行示例

9.1 系统启动到运行完整时序

时间线         事件                              函数调用
─────────────────────────────────────────────────────────────────────────────
0ms      [上电复位]
         │
1us      ├── SystemInit()                       时钟配置
         │   └── 设置PLL: 8MHz * 336 / 8 / 2 = 168MHz
         │
10us     ├── static_memory_pool_init()          内存池初始化
         │   ├── init_single_pool(SMALL)        1.5KB
         │   ├── init_single_pool(MEDIUM)       6KB
         │   ├── init_single_pool(LARGE)        12KB
         │   ├── init_single_pool(DMA)          12KB
         │   └── init_single_pool(STACK)        10KB
         │
20us     ├── OSInit()                           uCOS-II初始化
         │   ├── 创建空闲任务
         │   └── 创建统计任务
         │
30us     ├── OSTaskCreate(startup_task)         创建启动任务
         │   └── 优先级3,栈512B
         │
40us     ├── OSStart()                          启动调度器
         │   │
         │   ▼
50us     ├── [启动任务运行]
         │   ├── hal_spi_init()                 SPI初始化
         │   │   ├── hal_spi_create(1)          SPI1创建
         │   │   │   └── static_pool_alloc()   分配设备结构体
         │   │   ├── hal_spi_create(2)          SPI2创建
         │   │   └── hal_spi_create(3)          SPI3创建
         │   │
         │   ├── hal_uart_init()                UART初始化
         │   │   ├── hal_uart_create(1)         USART1
         │   │   ├── hal_uart_create(2)         USART2
         │   │   └── ...                        USART3/4/5/6
         │   │
         │   ├── hal_adc_init()                 ADC初始化
         │   │   ├── hal_adc_create(1)          ADC1
         │   │   └── hal_adc_create(2)          ADC2
         │   │
         │   ├── task_manager_create()          创建应用任务
         │   │   ├── SPI_Task (优先级5)
         │   │   ├── UART_Task (优先级6)
         │   │   ├── ADC_Task (优先级7)
         │   │   ├── Presenter (优先级10)
         │   │   └── Monitor (优先级20)
         │   │
         │   └── OSTaskDel(OS_PRIO_SELF)        删除自身
         │
100ms    ├── [SPI_Task运行]
         │   ├── hal_spi_config(10MHz, DMA)
         │   ├── double_buffer_create()
         │   └── spi_dev->transfer_double_buf()
         │       └── dma_manager_start()       启动DMA接收
         │
101ms    ├── [DMA中断]                         SPI数据到达
         │   ├── double_buffer_switch()        缓冲区切换
         │   └── OSSemPost(sem_data_ready)     唤醒SPI_Task
         │
102ms    ├── [SPI_Task处理数据]
         │   ├── double_buffer_get_ready()     获取缓冲区
         │   ├── spi_parse_frame()             解析数据
         │   └── data_model_update_spi()       更新数据模型
         │       └── notify_observers()        通知Presenter
         │
103ms    ├── [Presenter处理]
         │   ├── on_spi_data_changed()         数据变化回调
         │   ├── 数据格式化
         │   └── view->update_display()        显示数据
         │
104ms    ├── [UART_Task运行]
         │   ├── 等待接收中断
         │   └── 处理串口命令
         │
105ms    ├── [ADC_Task运行]
         │   ├── ADC_DMA_IRQHandler()          ADC采样完成
         │   └── data_model_update_adc()       更新ADC数据
         │
106ms    ├── [Monitor_Task运行]
         │   ├── 计算CPU使用率: 42%
         │   ├── 检查内存: 空闲12KB
         │   ├── 更新系统状态
         │   └── IWDG_ReloadCounter()          喂狗
         │
         └── 系统持续运行...

9.2 典型数据流示例

/* ============================================================================
 * 示例:SPI传感器数据采集完整流程
 * ============================================================================ */
​
/* 1. 硬件层 - DMA自动接收数据 */
// SPI硬件接收到数据 → DMA自动搬运到缓冲区0
// 缓冲区0满 → DMA中断触发
// DMA中断 → double_buffer_switch() 切换到缓冲区1
// DMA继续填充缓冲区1
​
/* 2. 驱动层 - 中断处理 */
void DMA2_Stream3_IRQHandler(void)
{
    OSIntEnter();
    // 清除中断标志
    DMA_ClearFlag(DMA2_Stream3, DMA_FLAG_TCIF3);
    // 切换缓冲区
    double_buffer_switch(spi_db);
    // 唤醒任务
    OSSemPost(spi_sem_ready);
    OSIntExit();
}
​
/* 3. 任务层 - SPI数据处理任务 */
void spi_task(void *p_arg)
{
    while (1) {
        // 等待数据就绪
        OSSemPend(spi_sem_ready, 0);
        
        // 获取就绪缓冲区
        int8_t buf_idx = double_buffer_get_ready(spi_db, &len);
        uint8_t *data = double_buffer_get_ptr(spi_db, buf_idx);
        
        // 解析数据帧
        if (data[0] == 0xAA && data[1] == 0x55) {
            SpiSensorData_t sensor_data;
            sensor_data.sensor_id = data[2];
            sensor_data.data_len = data[3];
            memcpy(sensor_data.data, &data[4], sensor_data.data_len);
            sensor_data.crc = *(uint16_t*)&data[4 + sensor_data.data_len];
            
            // 更新数据模型
            data_model_update_spi(model, &sensor_data);
        }
        
        // 释放缓冲区
        double_buffer_release(spi_db, buf_idx);
    }
}
​
/* 4. 模型层 - 数据模型更新 */
bool data_model_update_spi(DataModel_t *model, SpiSensorData_t *data)
{
    // 环形缓冲区写入
    memcpy(&model->spi_data[model->spi_write_idx], data, sizeof(SpiSensorData_t));
    model->spi_write_idx = (model->spi_write_idx + 1) % 8;
    
    // 通知观察者
    DataObserver_t *obs = model->observers[DATA_TYPE_SPI];
    while (obs) {
        obs->on_data_changed(obs, DATA_TYPE_SPI, data, sizeof(SpiSensorData_t));
        obs = obs->next;
    }
    
    return true;
}
​
/* 5. 展示层 - Presenter处理 */
void on_spi_data_changed(DataObserver_t *obs, DataType_t type, void *data, uint32_t len)
{
    SpiSensorData_t *sensor = (SpiSensorData_t *)data;
    DataPresenter_t *presenter = (DataPresenter_t *)obs->context;
    
    // 数据校验
    if (!sensor->is_valid) {
        presenter->view->show_alert(presenter->view, 0x1001, "CRC Error");
        return;
    }
    
    // 格式转换
    char display_buf[128];
    sprintf(display_buf, "Sensor %d: ", sensor->sensor_id);
    for (int i = 0; i < sensor->data_len && i < 16; i++) {
        sprintf(&display_buf[strlen(display_buf)], "%02X ", sensor->data[i]);
    }
    
    // 显示
    presenter->view->update_display(presenter->view, type, display_buf);
}

10. 编译配置与链接脚本

10.1 链接脚本完整配置

/* stm32f4xx_flash.ld - 完整链接脚本 */
​
/* 内存区域定义 */
MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 1024K
  SRAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 112K
  CCMRAM (rw)     : ORIGIN = 0x10000000, LENGTH = 64K
}
​
/* 栈顶地址 */
_estack = ORIGIN(CCMRAM) + LENGTH(CCMRAM);
​
SECTIONS
{
  /* 中断向量表 */
  .isr_vector : {
    . = ALIGN(4);
    KEEP(*(.isr_vector))
    . = ALIGN(4);
  } >FLASH
​
  /* 代码段 */
  .text : {
    . = ALIGN(4);
    *(.text)
    *(.text.*)
    *(.glue_7)
    *(.glue_7t)
    *(.eh_frame)
    KEEP(*(.init))
    KEEP(*(.fini))
    . = ALIGN(4);
    _etext = .;
  } >FLASH
​
  /* 只读数据段 */
  .rodata : {
    . = ALIGN(4);
    *(.rodata)
    *(.rodata.*)
    . = ALIGN(4);
  } >FLASH
​
  /* 初始化数据段 */
  .data : {
    . = ALIGN(4);
    _sdata = .;
    *(.data)
    *(.data.*)
    . = ALIGN(4);
    _edata = .;
  } >SRAM AT> FLASH
​
  /* 未初始化数据段 */
  .bss : {
    . = ALIGN(4);
    _sbss = .;
    *(.bss)
    *(.bss.*)
    *(COMMON)
    . = ALIGN(4);
    _ebss = .;
  } >SRAM
​
  /* DMA缓冲区段 - 32字节对齐,放在SRAM */
  .dma_ram (NOLOAD) : {
    . = ALIGN(32);
    _sdma = .;
    *(.dma_ram)
    *(.dma_ram.*)
    . = ALIGN(32);
    _edma = .;
  } >SRAM
​
  /* CCM RAM段 - CPU独占,零等待 */
  .ccmram (NOLOAD) : {
    . = ALIGN(8);
    _sccm = .;
    *(.ccmram)
    *(.ccmram.*)
    . = ALIGN(8);
    _eccm = .;
  } >CCMRAM
​
  /* 任务栈段 - 放在CCM RAM */
  .stack (NOLOAD) : {
    . = ALIGN(8);
    _stack_start = .;
    *(.stack)
    . = ALIGN(8);
    _stack_end = .;
  } >CCMRAM
}

第二部分 STM32F407嵌入式系统架构bug思路集

bug思路与详细解答


问题1:开机要延时多久,不会因为开机电压震荡到程序数据紊乱?

bug思路:

/**
 * @brief 开机延时设计 - 解决电源稳定问题
 * 
 * 分析:STM32F407上电后,外部晶振需要稳定时间(典型2ms)
 *       电源电压建立需要时间(取决于外部电容)
 *       外设初始化需要等待稳定
 */
​
/* 解决方案:分级延时 + 状态检测 */
void SystemPowerOnSequence(void)
{
    /* 1. 硬件级延时 - 等待电源稳定 */
    // 方法A:简单延时(保守设计)
    for (volatile uint32_t i = 0; i < 100000; i++);  // 约10ms @168MHz
    
    // 方法B:检测电源电压(推荐)
    while (PWR_GetFlagStatus(PWR_FLAG_VOS) == RESET);  // 等待电压调节器稳定
    
    /* 2. 时钟稳定检测 */
    RCC_HSEConfig(RCC_HSE_ON);
    while (RCC_WaitForHSEStartUp() == ERROR);  // 等待外部晶振稳定
    
    /* 3. 外设稳定延时 */
    HAL_Delay(10);  // 10ms延时,确保外设电源稳定
    
    /* 4. 内存初始化前等待 */
    __DSB();  // 数据同步屏障
    __ISB();  // 指令同步屏障
}

开机时序图:

┌─────────────────────────────────────────────────────────────────────────┐
│                        开机时序分析                                      │
└─────────────────────────────────────────────────────────────────────────┘
​
    VDD
    3.3V ┤
         │          ┌─────────────────────────────────────────────────────
         │          │
         │          │ 电压上升时间
         │          │ (典型1-5ms)
         │          │
    0V   └──────────┴─────────────────────────────────────────────────────
         ↑          ↑
         │          │
    上电时刻    电压稳定点
         │          │
         │          │  HSE起振时间
         │          │  (典型2ms)
         │          │
         │          └──┬──┐
         │             │  │
         │             │  │
         │             └──┴──────────────────────────────────────────────
         │                  ↑
         │                  │
         │              晶振稳定
         │                  │
         │                  │  外设初始化
         │                  │  (5-10ms)
         │                  │
         └──────────────────┴────────────────────────────────────────────
                             ↑
                             │
                         系统启动
                             (总延时: 10-20ms)

问题2:中断与DMA如何巧妙设计才不会数据覆盖而没有取走?

bug思路:

/**
 * @brief 双缓冲+环形缓冲区设计 - 防止数据覆盖
 * 
 * 核心思想:
 * 1. DMA使用双缓冲模式,自动切换
 * 2. 应用层使用环形缓冲区二次缓冲
 * 3. 使用信号量同步,避免竞态
 */
​
/*==============================================================================
 * 方案1:DMA双缓冲 + 环形缓冲区(推荐)
 *============================================================================*/
​
typedef struct {
    /* DMA双缓冲 */
    uint8_t dma_buf0[2048] __attribute__((aligned(32)));
    uint8_t dma_buf1[2048] __attribute__((aligned(32)));
    volatile uint8_t active_dma_buf;  // 0或1
    
    /* 环形缓冲区 */
    uint8_t ring_buf[8192];
    volatile uint32_t write_ptr;
    volatile uint32_t read_ptr;
    
    /* 同步信号量 */
    OS_EVENT *sem_data_ready;
    OS_EVENT *sem_buffer_free;
} SafeBuffer_t;
​
/**
 * @brief DMA中断处理 - 安全切换
 */
void DMA_IRQHandler(void)
{
    OSIntEnter();
    
    if (DMA_GetFlagStatus(DMA_Stream, DMA_FLAG_TCIF)) {
        DMA_ClearFlag(DMA_Stream, DMA_FLAG_TCIF);
        
        /* 1. 获取当前完成的缓冲区索引 */
        uint8_t completed_buf = active_dma_buf;
        
        /* 2. 切换到另一个缓冲区 */
        active_dma_buf ^= 1;
        DMA_SetCurrDataCounter(DMA_Stream, BUFFER_SIZE);
        
        /* 3. 将已完成的数据写入环形缓冲区(快速操作) */
        uint8_t *src = (completed_buf == 0) ? dma_buf0 : dma_buf1;
        uint32_t bytes_to_copy = BUFFER_SIZE;
        
        /* 检查环形缓冲区是否有足够空间 */
        uint32_t free_space = RING_BUFFER_SIZE - (write_ptr - read_ptr);
        
        if (free_space >= bytes_to_copy) {
            /* 有空间,写入环形缓冲区 */
            for (uint32_t i = 0; i < bytes_to_copy; i++) {
                ring_buf[write_ptr++ & RING_BUFFER_MASK] = src[i];
            }
            /* 通知任务有数据 */
            OSSemPost(sem_data_ready);
        } else {
            /* 缓冲区满,丢弃数据并记录溢出 */
            overflow_count++;
        }
    }
    
    OSIntExit();
}
​
/**
 * @brief 应用任务 - 安全读取数据
 */
void DataProcessTask(void *p_arg)
{
    while (1) {
        /* 等待数据就绪(超时机制) */
        if (OSSemPend(sem_data_ready, 100, &err) == OS_ERR_NONE) {
            /* 从环形缓冲区读取数据 */
            while (read_ptr < write_ptr) {
                uint8_t data = ring_buf[read_ptr++ & RING_BUFFER_MASK];
                ProcessData(data);
            }
        }
    }
}

数据流防覆盖设计图:

┌─────────────────────────────────────────────────────────────────────────┐
│                  数据流防覆盖设计                                        │
└─────────────────────────────────────────────────────────────────────────┘
​
    [SPI硬件]
         │
         │ 硬件自动传输
         ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │                    DMA双缓冲                                     │
    │  ┌─────────────────┐    ┌─────────────────┐                    │
    │  │   缓冲区0       │    │   缓冲区1       │                    │
    │  │   (2KB)        │    │   (2KB)        │                    │
    │  │                │    │                │                    │
    │  │  [DMA填充中]   │    │  [空闲]        │                    │
    │  └─────────────────┘    └─────────────────┘                    │
    │         │                      ▲                              │
    │         │ 缓冲区满              │                              │
    │         ▼                      │                              │
    │  ┌─────────────────┐    ┌─────────────────┐                    │
    │  │   缓冲区0       │    │   缓冲区1       │                    │
    │  │   [已满]       │───▶│   [DMA填充中]   │                    │
    │  └─────────────────┘    └─────────────────┘                    │
    │         │                      │                              │
    │         │ DMA中断触发          │                              │
    │         ▼                      │                              │
    └─────────┼──────────────────────┼──────────────────────────────┘
              │                      │
              │ 快速拷贝(关中断时间最小化)
              ▼                      ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │                    环形缓冲区 (8KB)                             │
    │  ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐          │
    │  │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │...│ N │          │
    │  └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘          │
    │    ▲                   ▲                                       │
    │    │                   │                                       │
    │ 读指针              写指针                                     │
    │ (任务读取)         (中断写入)                                  │
    └─────────────────────────────────────────────────────────────────┘
              │
              │ 信号量同步
              ▼
    [应用任务] 安全读取,不会覆盖

问题3:任务优先级反转是那种场景下发生?

bug思路:

/**
 * @brief 优先级反转场景分析
 * 
 * 定义:高优先级任务被低优先级任务阻塞,而中优先级任务占用CPU
 */
​
/*==============================================================================
 * 优先级反转场景演示
 *============================================================================*/
​
/* 三个任务:高、中、低优先级 */
#define TASK_PRIO_HIGH   5
#define TASK_PRIO_MID    10
#define TASK_PRIO_LOW    15
​
/* 共享资源互斥锁 */
OS_EVENT *shared_mutex;
​
/* 低优先级任务 - 占用共享资源 */
void LowPriorityTask(void *p_arg)
{
    while (1) {
        /* 获取共享资源 */
        OSMutexPend(shared_mutex, 0, &err);
        
        /* 长时间操作共享资源(如SPI通信100ms) */
        Spi_Transfer(large_buffer, 1024);
        
        /* 释放资源 */
        OSMutexPost(shared_mutex);
        
        OSTimeDly(100);
    }
}
​
/* 中优先级任务 - 不访问共享资源,但占用CPU */
void MidPriorityTask(void *p_arg)
{
    while (1) {
        /* 大量计算,长时间占用CPU */
        for (int i = 0; i < 1000000; i++) {
            Calculate();
        }
        OSTimeDly(10);
    }
}
​
/* 高优先级任务 - 需要访问共享资源 */
void HighPriorityTask(void *p_arg)
{
    while (1) {
        /* 尝试获取共享资源 */
        OSMutexPend(shared_mutex, 0, &err);
        
        /* 快速操作 */
        ProcessData();
        
        OSMutexPost(shared_mutex);
        
        OSTimeDly(10);
    }
}

优先级反转时序图:

┌─────────────────────────────────────────────────────────────────────────┐
│                  优先级反转时序图                                        │
└─────────────────────────────────────────────────────────────────────────┘
​
时间 →
    │
    │  低优先级任务(L)         中优先级任务(M)         高优先级任务(H)
    │
0ms ├── [L获取互斥锁] ─────────────────────────────────────────────────────
    │      │
    │      │ 执行长操作
    │      │
10ms├──────┼────────────────────────────────────── [H就绪,等待互斥锁] ──┐
    │      │                                           │                │
    │      │                                           │ 被阻塞        │
    │      │                                           │               │
20ms├──────┼────────────────── [M抢占CPU] ──────────────────────────────┤
    │      │                      │                                     │
    │      │                      │ 执行计算                            │
    │      │                      │ (占用CPU)                          │
    │      │                      │                                     │
30ms├──────┼──────────────────────┼─────────────────────────────────────┤
    │      │                      │                                     │
    │      │                      │                                     │
40ms├──────┼──────────────────────┼─────────────────────────────────────┤
    │      │                      │                                     │
    │      │                      │                                     │
50ms├──────┼──────────────────────┼─────────────────────────────────────┤
    │      │                      │                                     │
    │      │                      │                                     │
60ms├──────┼──────────────────────┼─────────────────────────────────────┤
    │      │                      │                                     │
    │      │                      │                                     │
70ms├──────┼──────────────────────┼─────────────────────────────────────┤
    │      │                      │                                     │
    │      │                      │                                     │
80ms├──────┼──────────────────────┼─────────────────────────────────────┤
    │      │                      │                                     │
    │      │ [L释放互斥锁]        │                                     │
    │      ▼                      │                                     │
    │  ┌──────────────────────────┴─────────────────────────────────────┐
    │  │                     [H获得互斥锁,开始执行]                    │
    │  └────────────────────────────────────────────────────────────────┘
    │
    │
    └── 结论:H任务被M任务间接阻塞了70ms,尽管M优先级低于H
​
    【解决方案】:使用优先级继承协议

解决方案:优先级继承

/**
 * @brief 使用uCOS-II的互斥锁(内置优先级继承)
 */
void PriorityInheritanceExample(void)
{
    /* uCOS-II的互斥锁自动实现优先级继承 */
    OS_EVENT *mutex;
    
    mutex = OSMutexCreate(0, &err);  // 创建互斥锁
    
    /* 当低优先级任务持有互斥锁时,其优先级临时提升到等待该锁的最高优先级 */
    /* 释放后恢复原优先级 */
}

问题4:你的程序会不会因为缓存区管理产生死锁?

bug思路:

/**
 * @brief 死锁场景分析与预防
 * 
 * 死锁必要条件:
 * 1. 互斥条件
 * 2. 持有并等待
 * 3. 不可剥夺
 * 4. 循环等待
 */
​
/*==============================================================================
 * 可能导致死锁的场景
 *============================================================================*/
​
/* 场景1:双缓冲区的生产者-消费者死锁 */
void PotentialDeadlock_ProducerConsumer(void)
{
    /* 错误设计:生产者等待空闲缓冲区,消费者等待满缓冲区 */
    
    // 生产者:
    OSSemPend(sem_empty, 0);      // 等待空缓冲区
    OSSemPend(sem_full, 0);       // 错误:不应等待满缓冲区
    // 可能导致:生产者持有空缓冲区信号量,等待满缓冲区
    
    // 消费者:
    OSSemPend(sem_full, 0);       // 等待满缓冲区
    OSSemPend(sem_empty, 0);      // 错误:不应等待空缓冲区
    // 可能导致:消费者持有满缓冲区信号量,等待空缓冲区
}
​
/* 正确设计:避免循环等待 */
void Correct_ProducerConsumer(void)
{
    // 生产者:只等待空缓冲区
    OSSemPend(sem_empty, 0);       // 等待空缓冲区
    // 写入数据
    OSSemPost(sem_full);           // 通知消费者
    
    // 消费者:只等待满缓冲区
    OSSemPend(sem_full, 0);        // 等待满缓冲区
    // 读取数据
    OSSemPost(sem_empty);          // 通知生产者
}

死锁预防设计:

/**
 * @brief 安全缓冲区管理器 - 预防死锁
 */
typedef struct {
    /* 双缓冲 */
    uint8_t *buf0;
    uint8_t *buf1;
    volatile uint8_t active;
    volatile uint8_t ready;
    
    /* 信号量 - 单一方向等待 */
    OS_EVENT *sem_producer;   // 生产者等待空缓冲区
    OS_EVENT *sem_consumer;   // 消费者等待满缓冲区
    
    /* 超时机制 */
    uint32_t timeout_ms;
} SafeDoubleBuffer_t;
​
/**
 * @brief 安全写入(生产者)
 * @return true-成功, false-超时
 */
bool SafeDoubleBuffer_Write(SafeDoubleBuffer_t *db, uint8_t *data, uint32_t len)
{
    OS_ERR err;
    
    /* 1. 等待空缓冲区(带超时) */
    if (OSSemPend(db->sem_producer, db->timeout_ms, &err) != OS_ERR_NONE) {
        return false;  // 超时返回,不会死锁
    }
    
    /* 2. 写入数据(临界区保护) */
    OS_ENTER_CRITICAL();
    uint8_t write_buf = (db->active == 0) ? 1 : 0;
    if (write_buf == 0) {
        memcpy(db->buf0, data, len);
    } else {
        memcpy(db->buf1, data, len);
    }
    db->ready = write_buf;
    OS_EXIT_CRITICAL();
    
    /* 3. 通知消费者 */
    OSSemPost(db->sem_consumer);
    
    return true;
}
​
/**
 * @brief 安全读取(消费者)
 * @return true-成功, false-超时
 */
bool SafeDoubleBuffer_Read(SafeDoubleBuffer_t *db, uint8_t *data, uint32_t *len)
{
    OS_ERR err;
    
    /* 1. 等待满缓冲区(带超时) */
    if (OSSemPend(db->sem_consumer, db->timeout_ms, &err) != OS_ERR_NONE) {
        return false;  // 超时返回
    }
    
    /* 2. 读取数据 */
    OS_ENTER_CRITICAL();
    uint8_t read_buf = db->ready;
    if (read_buf == 0) {
        memcpy(data, db->buf0, BUFFER_SIZE);
    } else {
        memcpy(data, db->buf1, BUFFER_SIZE);
    }
    db->active = read_buf;
    OS_EXIT_CRITICAL();
    
    /* 3. 通知生产者有空缓冲区 */
    OSSemPost(db->sem_producer);
    
    return true;
}

死锁预防策略总结:

/* 预防死锁的5个策略 */
typedef enum {
    DEADLOCK_PREVENTION_1 = 0,  // 破坏互斥条件(使用无锁设计)
    DEADLOCK_PREVENTION_2,       // 破坏持有并等待(一次性申请所有资源)
    DEADLOCK_PREVENTION_3,       // 破坏不可剥夺(超时机制)
    DEADLOCK_PREVENTION_4,       // 破坏循环等待(固定资源顺序)
    DEADLOCK_PREVENTION_5        // 银行家算法(资源预分配)
} DeadlockPrevention_t;
​
/* 本系统采用的策略 */
void SystemDeadlockPrevention(void)
{
    /* 1. 破坏循环等待:统一资源申请顺序 */
    // 规则:总是先申请DMA通道,再申请缓冲区,最后申请互斥锁
    
    /* 2. 破坏不可剥夺:所有资源申请都带超时 */
    OSMutexPend(mutex, timeout, &err);  // 带超时
    
    /* 3. 破坏持有并等待:使用一次性申请 */
    // 在任务开始时一次性申请所有需要的资源
    
    /* 4. 使用uCOS-II的内置机制 */
    // - 互斥锁的优先级继承
    // - 信号量的超时机制
}

问题5:操作系统特性还有哪些没有使用,如果全部要用,又如何设计?

bug思路:

/**
 * @brief uCOS-II完整特性应用设计
 * 
 * 未使用的特性清单及设计方案
 */
​
/*==============================================================================
 * 1. 事件标志组 (Event Flags) - 多事件同步
 *============================================================================*/
​
/* 应用场景:多个外设数据就绪后才处理 */
void EventFlagsDesign(void)
{
    OS_FLAG_GRP *data_ready_flags;
    
    /* 创建事件标志组 */
    data_ready_flags = OSFlagCreate(0, &err);
    
    /* SPI任务:数据就绪时设置标志 */
    void spi_task(void *p_arg)
    {
        while (1) {
            WaitForData();
            OSFlagPost(data_ready_flags, 0x01, OS_FLAG_SET, &err);
        }
    }
    
    /* ADC任务:数据就绪时设置标志 */
    void adc_task(void *p_arg)
    {
        while (1) {
            WaitForData();
            OSFlagPost(data_ready_flags, 0x02, OS_FLAG_SET, &err);
        }
    }
    
    /* UART任务:数据就绪时设置标志 */
    void uart_task(void *p_arg)
    {
        while (1) {
            WaitForData();
            OSFlagPost(data_ready_flags, 0x04, OS_FLAG_SET, &err);
        }
    }
    
    /* 融合任务:等待所有数据就绪 */
    void fusion_task(void *p_arg)
    {
        while (1) {
            /* 等待SPI、ADC、UART全部就绪 */
            OSFlagPend(data_ready_flags, 0x07, OS_FLAG_WAIT_SET_ALL, 0, &err);
            
            /* 所有数据就绪,执行融合处理 */
            DataFusion();
            
            /* 清除标志 */
            OSFlagPost(data_ready_flags, 0x07, OS_FLAG_CLR, &err);
        }
    }
}
​
/*==============================================================================
 * 2. 任务内建消息队列 (Task Built-in Queue)
 *============================================================================*/
​
/* 应用场景:每个任务独立的消息队列,减少全局消息中心 */
void BuiltInQueueDesign(void)
{
    /* 配置:使能任务内建消息队列 */
    // os_cfg.h: #define OS_TASK_Q_EN 1
    
    /* 创建任务时指定消息队列大小 */
    OSTaskCreateExt(task_func,
                    NULL,
                    &stack[0],
                    TASK_PRIO,
                    TASK_PRIO,
                    &stack[STACK_SIZE-1],
                    STACK_SIZE,
                    (void *)0,
                    OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK,
                    &err);
    
    /* 发送消息到指定任务 */
    void SendMessageToTask(OS_TCB *task_tcb, void *msg)
    {
        OSTaskQPost(task_tcb, msg, sizeof(msg), &err);
    }
    
    /* 接收消息 */
    void task_func(void *p_arg)
    {
        void *msg;
        INT8U msg_size;
        
        while (1) {
            msg = OSTaskQPend(0, &msg_size, &err);
            ProcessMessage(msg);
        }
    }
}
​
/*==============================================================================
 * 3. 定时器服务 (Timer Service)
 *============================================================================*/
​
/* 应用场景:周期性任务、超时检测、看门狗刷新 */
void TimerServiceDesign(void)
{
    /* 创建定时器 */
    OS_TMR *timer;
    
    timer = OSTmrCreate(10,      // 初始延迟10个节拍
                        100,      // 周期100个节拍
                        OS_TMR_OPT_PERIODIC,  // 周期性
                        TimerCallback,        // 回调函数
                        "MyTimer",
                        &err);
    
    /* 启动定时器 */
    OSTmrStart(timer, &err);
    
    /* 定时器回调(在定时器任务上下文中执行) */
    void TimerCallback(void *p_arg)
    {
        /* 执行周期性任务,如传感器数据采集 */
        CollectSensorData();
        
        /* 或刷新看门狗 */
        IWDG_ReloadCounter();
        
        /* 或发送消息到任务 */
        OSTaskQPost(sensor_task_tcb, &data, sizeof(data), &err);
    }
}
​
/*==============================================================================
 * 4. 内存分区管理 (Memory Partition)
 *============================================================================*/
​
/* 应用场景:固定大小内存块管理,替代静态池 */
void MemoryPartitionDesign(void)
{
    OS_MEM *mem_partition;
    INT8U partition_mem[100 * 64];  // 100个64字节块
    
    /* 创建内存分区 */
    mem_partition = OSMemCreate(partition_mem, 100, 64, &err);
    
    /* 分配内存 */
    void *block = OSMemGet(mem_partition, &err);
    
    /* 释放内存 */
    OSMemPut(mem_partition, block);
    
    /* 优点:比静态池更灵活,可动态创建/删除分区 */
}
​
/*==============================================================================
 * 5. 钩子函数 (Hooks)
 *============================================================================*/
​
/* 应用场景:系统调试、性能监控、任务跟踪 */
void HooksDesign(void)
{
    /* 空闲任务钩子 - 低功耗模式 */
    void App_IdleTaskHook(void)
    {
        /* 进入低功耗模式 */
        __WFI();  // 等待中断唤醒
    }
    
    /* 任务切换钩子 - 任务跟踪 */
    void App_TaskSwHook(void)
    {
        /* 记录任务切换时间 */
        uint32_t now = DWT->CYCCNT;
        TaskSwitchTime = now - last_switch_time;
        last_switch_time = now;
        
        /* 更新任务运行时间 */
        current_task->runtime += TaskSwitchTime;
    }
    
    /* 统计任务钩子 - CPU使用率 */
    void App_StatTaskHook(void)
    {
        /* 计算每个任务的CPU使用率 */
        CalculateTaskCPUUsage();
    }
    
    /* 系统启动钩子 */
    void App_StartupHook(void)
    {
        /* 初始化硬件 */
        SystemClock_Config();
        
        /* 打印启动信息 */
        printf("uCOS-II Startup\n");
    }
}

完整特性集成设计:

/**
 * @file full_ucos_features.c
 * @brief uCOS-II全部特性集成设计
 */
​
typedef struct {
    /* 1. 任务管理 */
    OS_TCB tasks[TASK_MAX];
    uint8_t task_priorities[TASK_MAX];
    
    /* 2. 同步机制 */
    OS_EVENT *mutex_list[MUTEX_MAX];
    OS_EVENT *sem_list[SEM_MAX];
    OS_FLAG_GRP *flag_groups[FLAG_MAX];
    
    /* 3. 通信机制 */
    OS_Q *queues[QUEUE_MAX];
    OS_MEM *mem_partitions[MEM_PART_MAX];
    
    /* 4. 定时器 */
    OS_TMR *timers[TIMER_MAX];
    
    /* 5. 任务内建队列 */
    uint8_t task_q_enabled[TASK_MAX];
} FullUcosSystem_t;
​
/**
 * @brief 完整特性系统初始化
 */
void FullUcosSystemInit(void)
{
    OS_ERR err;
    
    /* 1. 初始化内核 */
    OSInit();
    
    /* 2. 创建内存分区 */
    OS_MEM *msg_pool = OSMemCreate(msg_mem, MSG_COUNT, MSG_SIZE, &err);
    OS_MEM *data_pool = OSMemCreate(data_mem, DATA_COUNT, DATA_SIZE, &err);
    
    /* 3. 创建事件标志组 */
    OS_FLAG_GRP *sync_flags = OSFlagCreate(0, &err);
    
    /* 4. 创建互斥锁(带优先级继承) */
    OS_EVENT *shared_mutex = OSMutexCreate(0, &err);
    
    /* 5. 创建消息队列 */
    OS_Q *cmd_queue = OSQCreate(cmd_queue_buf, CMD_QUEUE_SIZE);
    
    /* 6. 创建定时器 */
    OS_TMR *heartbeat = OSTmrCreate(0, 100, OS_TMR_OPT_PERIODIC,
                                      HeartbeatCallback, NULL, "Heartbeat", &err);
    OSTmrStart(heartbeat, &err);
    
    /* 7. 创建任务(启用内建消息队列) */
    OSTaskCreateExt(Task1,
                    NULL,
                    &stack1[0],
                    TASK1_PRIO,
                    TASK1_PRIO,
                    &stack1[STACK_SIZE-1],
                    STACK_SIZE,
                    (void *)0,
                    OS_TASK_OPT_STK_CLR | OS_TASK_OPT_STK_CHK | OS_TASK_OPT_TASK_Q_EN,
                    &err);
    
    /* 8. 启动系统 */
    OSStart();
}
​
/**
 * @brief 完整特性应用示例
 */
void FullFeatureApplication(void)
{
    /* 场景1:多源数据同步采集 */
    void DataSyncTask(void *p_arg)
    {
        OS_FLAG_GRP *sync_flags;
        OS_ERR err;
        
        while (1) {
            /* 等待SPI、ADC、UART三个标志全部置位 */
            OSFlagPend(sync_flags, 0x07, OS_FLAG_WAIT_SET_ALL, 0, &err);
            
            /* 从内存分区获取缓冲区 */
            void *buf = OSMemGet(mem_partition, &err);
            
            /* 数据融合处理 */
            DataFusion(buf);
            
            /* 通过消息队列发送结果 */
            OSQPost(cmd_queue, buf);
            
            /* 清除标志 */
            OSFlagPost(sync_flags, 0x07, OS_FLAG_CLR, &err);
        }
    }
    
    /* 场景2:周期性任务 + 超时检测 */
    void TimerTask(void *p_arg)
    {
        OS_TMR *timer;
        OS_ERR err;
        
        timer = OSTmrCreate(0, 1000, OS_TMR_OPT_PERIODIC,
                            TimerCallback, NULL, "Periodic", &err);
        OSTmrStart(timer, &err);
        
        while (1) {
            /* 等待消息队列,带超时 */
            void *msg = OSQPend(cmd_queue, 100, &err);
            if (err == OS_ERR_TIMEOUT) {
                /* 超时处理 */
                HandleTimeout();
            } else {
                ProcessMessage(msg);
            }
        }
    }
    
    /* 场景3:钩子函数应用 */
    void HooksApplication(void)
    {
        /* 空闲任务钩子 - 进入睡眠模式 */
        OSTaskIdleHook = IdleHook;
        
        /* 统计任务钩子 - 记录任务CPU使用率 */
        OSTaskStatHook = StatHook;
        
        /* 任务切换钩子 - 任务跟踪 */
        OSTaskSwHook = TaskSwitchHook;
    }
}

bug思路总结清单

问题类别问题内容回答要点
启动时序开机延时设计10-20ms分级延时,电压检测,晶振稳定
数据保护中断/DMA防覆盖双缓冲+环形缓冲区+信号量同步
调度问题优先级反转互斥锁优先级继承机制
死锁预防缓冲区死锁单向等待+超时机制+资源顺序
系统特性未使用特性事件标志组、任务队列、定时器、内存分区、钩子函数
架构设计HAL+双缓冲+MVP分层架构、设计模式应用
竞态处理多环境竞态临界区、互斥锁、信号量、禁用中断
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐