/* ----------------------------------------------------------------------------- * linker.ld —— 扫雷程序的内存布局 * * 这颗 CPU 是"哈佛"结构:指令从 ROM 取(instr_addr_o),数据访问 RAM * (data_addr_o),两个地址空间都从 0 开始,所以这里用两个 MEMORY 区域, * 都在 0 处开头。 * * ROM 0x0000_0000 32 KB(= cpu21_board_top 的 ROM_WORDS = 8192 字) * +0x0000 .text.init 复位入口 _start * +0x0100 .text.isr1 中断入口 isr1_entry(关卡/游戏,**必须等于 IRQ1_VECTOR**) * +0x0200 .text.isr2 中断入口 isr2_entry(鼠标读取,必须等于 IRQ2_VECTOR) * +0x0300 .text.isr3 中断入口 isr3_entry(备用,必须等于 IRQ3_VECTOR) * +0x0400 .text 其余代码(紧跟 isr3 之后) * * RAM 0x0000_0000 4 KB(= saolei_board_top 的 RAM_WORDS = 1024 字) * +0x0000 .bss 全局变量(全部零初始化,不需要 ROM 里的初值) * +0x0FFC __stack_top 栈顶(向下增长) * * 两个断言很关键(都是这颗 CPU 的硬限制): * 1) 不能有 .data —— 数据空间读不到 ROM,没有地方放"带初值的变量", * 所有全局变量必须零初始化; * 2) 不能有 .rodata —— 同理,程序里不能出现字符串/常量表 * (字模在 RTL 里,不在软件里)。 * ---------------------------------------------------------------------------*/ ENTRY(_start) MEMORY { ROM (rx) : ORIGIN = 0x00000000, LENGTH = 32K RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 4K } SECTIONS { /* ------------------------- 数据段(RAM) ------------------------- */ . = 0x00000000; .bss (NOLOAD) : { __bss_start = .; *(.sbss) *(.sbss.*) *(.bss) *(.bss.*) *(COMMON) . = ALIGN(4); __bss_end = .; } > RAM /* 有初值的变量:不允许(见文件头的说明) */ .data : { *(.data) *(.data.*) *(.sdata) *(.sdata.*) } > RAM /* 只读数据:不允许(没有 auipc / 数据空间读不到 ROM) */ .rodata : { *(.rodata) *(.rodata.*) } > RAM ASSERT(SIZEOF(.data) == 0, "错误:程序里出现了带初值的全局变量(.data),这颗核没有地方存放它") ASSERT(SIZEOF(.rodata) == 0, "错误:程序里出现了字符串或常量表(.rodata),这颗核读不到 ROM 里的数据") /* ------------------------- 代码段(ROM) ------------------------- * 三个中断入口的地址**必须写在段声明里**(.text.isr1 0x100 : ...): * 只写 ". = 0x100;" 这种位置计数器赋值,在段带 "> ROM" 时会被 ld 忽略, * 它会按区域顺序把段紧挨着排下去(实测 isr1 掉到了 0x14)。 * 这三个地址要和顶层 cpu21_board_top 的 IRQ1/2/3_VECTOR 参数一致。 */ .text.init 0x00000000 : { KEEP(*(.text.init)) } > ROM .text.isr1 0x00000100 : /* IRQ1:关卡(游戏)入口 */ { KEEP(*(.text.isr1)) } > ROM .text.isr2 0x00000200 : /* IRQ2:鼠标读取 */ { KEEP(*(.text.isr2)) } > ROM .text.isr3 0x00000300 : /* IRQ3:备用 */ { KEEP(*(.text.isr3)) } > ROM .text : { *(.text) *(.text.*) . = ALIGN(4); } > ROM /* ------------------------- 符号 ------------------------- */ __stack_top = ORIGIN(RAM) + LENGTH(RAM) - 4; /* 0x0FFC */ __isr_vector = 0x00000100; /* .bss 不能长到撞到栈 */ ASSERT(__bss_end < (__stack_top - 0x200), "错误:.bss 太大,会覆盖栈;请缩小棋盘或加大 RAM_WORDS") }