内存空间总览
不同存储空间承担不同职责,地址应分别理解。
高速任务启动与删除、调度原因、中断状态、调度模式和临界区状态等位变量。
包括固定地址的中断编号保护、R0 保护以及内核工作变量;另有位于 0x15 的中断嵌套临时变量。
通过固定地址数组划分系统堆栈保护区、中断堆栈区和用户任务堆栈区。
保存当前任务、上一个任务、调度触发源、时间片、临界区嵌套状态及中断现场数据。
集中存放任务状态、上下文、SP 记录、任务控制块、统一资源对象和消息队列对象。
BIT 状态标志区
以位变量表示内核控制状态。
当前实现使用 volatile bit
定义多项内核状态标志。它们用于高速任务控制、调度判断、中断状态维护和临界区管理。
这些标志不应与普通字节变量或 XDATA 对象混为一谈。
volatile bit OS_KUAI_PROCESS_A;
volatile bit OS_KUAI_PROCESS_B;
volatile bit OS_KUAI_PROCESS_A_DEL;
volatile bit OS_KUAI_PROCESS_B_DEL;
volatile bit OS_JINCHENG_CUNCHU;
volatile bit OS_SCHED_REASON;
volatile bit OS_ISR_FLAG;
volatile bit OS_INTERRUPT_T0;
volatile bit OS_RTOS_YES;
volatile bit OS_a;
volatile bit OS_b;
volatile bit OS_INTERRUPT_GAO;
volatile bit OS_INTERRUPT_GAO_BIAO;
volatile bit os_int_status;
volatile bit OS_CFG_LOCK;
volatile 表示这些对象可能在当前执行路径之外被改变,
编译器需要按相应的易变对象规则处理访问;它本身不等于完整的并发保护机制。
DATA 固定地址变量
直接寻址的内核工作变量与保护变量。
| 地址 | 变量 | 用途 |
|---|---|---|
| 0x15 | OS_IRQ_NEST_TEMP |
中断嵌套临时变量 |
| 0x30 | OS_INTERRUPT_PROTECT |
中断编号保护 |
| 0x31 | OS_R0_PROTECT |
R0 寄存器保护 |
| 0x32 | os_sp |
通用工作变量 |
| 0x33 | OS_HRTOS |
内核临时变量 |
| 0x34 | OS_HRTOS_2 |
中断保护相关变量 |
堆栈区域
固定地址划分的三段堆栈相关区域。
0x35 起 · OS_SP_KER 字节
0x3A–0x41 · 8 B
0x42–0x7F · 62 B
unsigned char data OS_HRTOS_DUIZHAN_OS[OS_SP_KER]
_at_ 0x35;
unsigned char data OS_HRTOS_DUIZHAN_INT[8]
_at_ 0x3A;
unsigned char data OS_HRTOS_DUIZHAN_APP[62]
_at_ 0x42;
这三个区域在地址规划上分别承担系统、中断和用户任务相关的堆栈用途。 实际栈深度、安全余量以及调用路径是否可能超出区域边界,需要结合汇编、编译结果和运行时测量验证。
OS_SP_KER 决定。
在确认该宏的最终取值前,不应将系统堆栈长度写成固定值。
IDATA 调度与中断状态区
在固定内部 RAM 地址保存关键调度状态。
| 地址 | 变量 | 用途 |
|---|---|---|
| 0xE7 | os_critical_nesting | 临界区嵌套计数 |
| 0xE6 | OS_TIME_XY | 当前时间片状态 |
| 0xE5 | OS_DISPATCH_ID | 调度触发源 |
| 0xE4 | OS_PREV_TASK | 上一个任务 ID |
| 0xE3 | OS_CURRENT_TASK | 当前任务 ID |
| 0xE2 | OS_T0_TH0 | Timer0 TH0 相关保存值 |
| 0xE1 | OS_T0_TL0 | Timer0 TL0 相关保存值 |
中断现场保护区
volatile unsigned char idata OS_INT_BAO[6]
_at_ 0xDB;
/* 按当前注释约定:
* 0xE0 - ACC
* 0xDF - B
* 0xDE - DPH
* 0xDD - DPL
* 0xDC - PSW
* 0xDB - EA / 备用
*/
现场保存顺序和恢复顺序需要与实际中断入口、退出汇编保持一致。 表中的寄存器对应关系来自当前内存定义注释,不代表已经独立验证所有中断路径。
XDATA 全局内存池
以 0x0200 为基地址,通过偏移量组织内核数据。
当前规划的系统全局内存池大小为 512 字节,地址范围是
0x0200–0x03FF。
任务状态、上下文、SP 记录、调度数据及内核对象均在这段 XDATA 中安排固定位置。
#define OS_SYS_GLOBAL_BASE 0x0200
#define OS_SYS_GLOBAL_SIZE 512
#define OS_SYS_GLOBAL_END \
(OS_SYS_GLOBAL_BASE + OS_SYS_GLOBAL_SIZE - 1)
任务上下文与基础管理区
| 地址范围 | 对象 | 大小 |
|---|---|---|
| 0x0200–0x020F | OS_PROCESS_OK | 16 B |
| 0x0210–0x021F | OS_JINCHENG_SP | 16 B |
| 0x0220–0x0221 | OS_KUAI_SP | 2 B |
| 0x0222–0x022B | OS_FAST_CONTEXT | 10 B |
| 0x022C–0x02FB | OS_TASK_CONTEXT | 208 B |
| 0x02FC–0x02FF | OS_MEMORY | 4 B |
| 0x0300–0x030F | OS_JINCHENG_JILU_SP | 16 B |
时间、等待、中断与事件状态区
| 地址范围 | 对象 | 大小 |
|---|---|---|
| 0x0310 | OS_TIME_ONCE | 1 B |
| 0x0311–0x0314 | OS_WAIT_DI2 | 4 B |
| 0x0315–0x0316 | OS_INTERRUPT_ADDR | 2 B |
| 0x0317–0x0318 | OS_INTERRUPT_ADDR2 | 2 B |
| 0x0319–0x031A | OS_TICK_COUNT_L | 2 B |
| 0x031B–0x031C | OS_TICK_COUNT_H | 2 B |
| 0x031D | OS_EVENT_BIT | 1 B |
| 0x031E | OS_STACK_WARN | 1 B |
| 0x031F–0x0320 | OS_KUAI_BEI | 2 B |
| 0x0321–0x0322 | OS_KUAI_BEI2 | 2 B |
| 0x0323–0x0334 | OS_TASK_EVENT | 18 B |
| 0x0335 | OS_TIME_ONCE_BACKUP | 1 B |
内核对象区
任务控制块记录任务优先级、状态与等待信息; 统一资源对象承载信号量、互斥锁、事件等资源的状态与等待队列; 消息队列对象则保存缓冲区指针及读写管理信息。
| 对象 | 声明大小 | 当前代码中的地址表达式 |
|---|---|---|
OS_TASK |
128 B | BASE + 0x0125 |
OS_RES |
36 B | BASE + 0x01A5 |
OS_MSGQ |
21 B | BASE + 0x01C9 |
OS_TASK @ 0x0336、
OS_RES @ 0x03B6、
OS_MSGQ @ 0x03DA;
但对应的 _at_ (OS_SYS_GLOBAL_BASE + offset)
声明分别计算为 0x0325、
0x03A5 和
0x03C9。
两组地址相差 0x11 字节。这里先明确列出声明表达式,不将两组互相矛盾的地址同时当作最终布局。
正式发布前应以最终编译使用的源文件、链接映射及 HEX 对应版本核实。
内存预算与资源占用
固定池大小明确,但最终使用量必须与实际编译布局一致。
当前内存注释声明全局池为 512 字节,规划使用至
0x03EF,剩余
0x03F0–0x03FF 共 16 字节。
不过,由于内核对象地址注释与偏移表达式存在差异,
在完成地址核对之前,不宜将 496 字节使用量视为已经验证的最终编译结果。
设计要点
从地址组织理解内核实现,而不是只看内存总量。
通过基地址、偏移宏和固定地址声明,明确内核数据的预期位置。
标准任务与高速任务使用不同的上下文区域,具体内容由当前上下文保存实现决定。
任务控制块、统一资源对象与消息队列对象分别存放,支撑调度和 IPC 功能。
最终地址、对象尺寸、堆栈边界与编译器映射应保持一致,避免注释与实际二进制脱节。