跳转至

systick开发指南

概述

Systick(System Tick)模块基于外部32.768kHz晶振或内部32kHz时钟为系统提供计数功能。

计数系统架构

**计数系统架构**

快速跑通 Systick Demo

功能说明

Systick 计时示例 在 20 ms 等待前后读取 Systick 毫秒计数并校验计数向前推进,不依赖外接硬件。

Demo 代码归档路径

samples/native_samples/systick/
├── CMakeLists.txt       # 独立组件构建配置
├── README.md            # 项目级运行说明
├── systick_demo.c       # 计数增量验证和 AT 指令
└── systick_demo.h       # 对外运行接口和 AT 注册函数声明

编译与烧录

完成一站式 CLI 环境配置后执行:

fbb set-target pack_diting_community
fbb build

使用一站式 CLI 烧写固件并打开 UART2 串口监视器。以下为 Windows USB DFU 示例;将 COM3 替换为实际日志串口,其他参数参见一站式 CLI 开发环境使用指南

fbb flash -f "$env:FBB_SDK_DIR\output\3322\fwpkg\diting-community.fwpkg" --chip 3322 -d --timeout 180
fbb monitor --port COM3 --baud 750000

使用方式

AT+SYSTICKTEST

预期结果

实际增量可能受任务调度影响而略大于 20 ms:

[DRV][SYSTICK] delta=20ms
[DRV][SYSTICK] PASS
OK

需要一次性检查 Systick、Systime、TCXO 等板载能力时,也可以执行 AT+DRIVERSELFTEST

文件结构与代码走读

文件职责

文件 职责 关键内容
systick_demo.c 读取毫秒计数、等待并校验增量 diting_systick_demo_run()
systick_demo.h 公开运行和 AT 注册接口 at_diting_systick_example_cmd_register()
CMakeLists.txt 定义独立组件和注册宏 diting_systick_sampleAT_DITING_EXAMPLE_SYSTICK_TEST
README.md 说明运行方法和预期结果 AT+SYSTICKTEST

核心流程

bool diting_systick_demo_run(void)
{
    uint64_t before = uapi_systick_get_ms();
    (void)osal_msleep(SYSTICK_DEMO_DELAY_MS);
    uint64_t delta = uapi_systick_get_ms() - before;
    printf("[DRV][SYSTICK] delta=%llums\n", (unsigned long long)delta);
    return delta >= SYSTICK_DEMO_DELAY_MS;
}

这里使用 osal_msleep() 让出 CPU,Systick 只负责提供前后计数。判断条件使用“不小于 20 ms”,避免任务调度造成的正常延迟被误判为失败。AT 处理函数输出单项结果,聚合自测通过同一公开函数复用这段逻辑。

基于 Systick Demo 开发自己的应用

  1. 复制 samples/native_samples/systick,修改组件名和构建开关,保留 diting_systick_demo_run() 这类可直接调用的运行函数。
  2. 从应用任务、系统服务或 app_run 启动入口调用运行函数。
  3. 根据精度要求选择 uapi_systick_get_s()uapi_systick_get_ms()uapi_systick_get_us()
  4. 测量任务执行时间时只包围目标代码;需要主动延时时,根据场景选择 OS 睡眠或 Systick 延时接口。
  5. 不要将任务调度延迟等同于 Systick 误差,应给验收范围保留合理裕量。
  6. 在上层 CMake 和目标配置中增加新组件入口。

需要串口触发板端回归时,可再配置 AT 命令名、命令 ID 和 AT 适配层注册;业务计时功能不依赖该调试入口。

功能描述

Systick模块提供的接口:

接口名称 功能简述 API文档
uapi_systick_init 初始化Systick模块 systick.md
uapi_systick_get_count 获取Systick当前计数值 systick.md
uapi_systick_get_s 获取Systick当前计数秒值 systick.md
uapi_systick_get_ms 获取Systick当前计数毫秒值 systick.md
uapi_systick_get_us 获取Systick当前计数微秒值 systick.md
uapi_systick_count_clear 清除Systick计数值 systick.md
uapi_systick_delay_s 按秒数延时 systick.md
uapi_systick_delay_ms 按毫秒数延时 systick.md
uapi_systick_delay_us 按微秒数延时 systick.md
uapi_systick_delay_count 按计数值延时 systick.md

开发指引

操作流程

操作流程

初始化Systick

uapi_systick_init();

获取计数值

uint64_t count;
count = uapi_systick_get_count();
PRINT("Systick count: %llu\r\n", count);

获取时间值

uint64_t seconds;
uint64_t milliseconds;
uint64_t microseconds;

seconds = uapi_systick_get_s();
milliseconds = uapi_systick_get_ms();
microseconds = uapi_systick_get_us();

PRINT("Time: %llu s, %llu ms, %llu us\r\n", seconds, milliseconds, microseconds);

清除计数

errcode_t ret;
ret = uapi_systick_count_clear();
if (ret != ERRCODE_SUCC) {
    return ret;
}

延时功能

// 延时1秒
uapi_systick_delay_s(1);

// 延时100毫秒
uapi_systick_delay_ms(100);

// 延时1000微秒
uapi_systick_delay_us(1000);

// 按count延时(count数取决于时钟频率)
uapi_systick_delay_count(32768);  // 约1秒(基于32.768kHz)

延时验证示例

void test_systick_delayms(void)
{
    uint64_t count_before_delay_count;
    uint64_t count_after_delay_count;

    /* systick模块初始化 */
    uapi_systick_init();

    /* 通过count数差值验证延迟时间 */
    count_before_delay_count = uapi_systick_get_count();
    uapi_systick_delay_ms(1000);  // 延时1秒
    count_after_delay_count = uapi_systick_get_count();

    printf("test case delay count %lu.\r\n",
           count_before_delay_count - count_after_delay_count);

    return;
}

注意事项

  1. 时钟源:基于外部32.768kHz晶振或内部32kHz时钟

  2. 计数频率:32.768kHz时,每计数一次约30.5μs

  3. 溢出:计数值类型为uint64_t,溢出概率极低

  4. 延时精度:受时钟源精度影响

**延时精度**:受时钟源精度影响

延时时间计算:

  • 延时1秒 ≈ 32768 count(基于32.768kHz)
  • 延时1ms ≈ 32.768 count
  • 延时1μs ≈ 0.032768 count