每次拿到別人或是原廠的 code,總是包含一堆 #ifdef,有的還是巢狀 #if #else,看到最後都快暈倒了。最後為了看是否此段原始碼到底有沒有被 compile,總是要耗費不少時間,有時還會看錯咧。
#pragma message "test"
今天讓我發現一個好用的巨集指令,也就是 #pragma message。只要在程式碼的上一行加入 #pragma message "test",然後再經過編譯,看一下編譯結果有沒有一個 warning 叫 "test" 就知道此段程式碼有被編譯,而不用幸苦的對程式碼。
※ INITCODE
INICODE 用來自動產生 reset vector,堆疊初始化,週邊初始化。
Syntax: INITCODE [BOOT386] [RESET|NORESET] [NOTHING] [STACK|NOSTACK] [ioport=data]
[OUTBYTE addr16=value8] [OUTWORD addr16=value16] [OUTDWORD addr16=value32]
[INBYTE addr16] [INWORD addr16] [INDWORD addr16]
[WRITEBYTE addr32=value8] [WRITEWORD addr32=value16] [WRITEDWORD addr32=value32]
[READBYTE addr32] [READWORD addr32] [READDWROD addr32]
[filename=file.ext CLASS=class_name]
- BOOT386: 產生與 386 以後 cpu 的相容開機引導程式。
- RESET: 在 FFFF0H 產生一段 far jump 到程式開始的位址。
- NOTHING: 強制產生 class ??LOCATE。
- STACK: 產生 SS:SP 初始化程式碼,會放在 class ??LOCATE 的 segment ??STACKINIT。
- ioport: 允許週邊暫存器透過檔案初始化,會放在 class ??LOCATE 的 segment ??CPUINIT。
- OUTBYTE/INBYTE: GPIO 的讀寫操作。
- WRITEBYTE/READBYTE: 記憶體的讀寫操作。
- INITCODE NOTHING: 建立一個 segment 包含一個 far jump 到程式進入點,沒有包含任何初始碼。
- INITCODE filename=file.ext CLASS=class_name
把 file.ext(binary) 放到 class_name,並把 code 放到 startup code execution list。
Examples 範例
- cputype i80186
initcode reset umcs=0xf038 lmcs=0x0ff8 - initcode outbyte 0xfffe=0x11
※ LISTFILE
LISTFILE 用來設定 listing file 要包含那些資料。
Syntax: LISTFILE [SEGMENTS] [PUBLICS[BY ADDRESS|BY NAME] [COLUMNS=(1|2)] [WIDTH=(80|132)] [SYMBOLS] [LINES] [REGIONS] [CHECKSUMS] [FILENAME=file]
- SEGMENTS: 建立一個 absolute segment map,包含 segment 的開始位置,結束位置,長度。
- REGIONS: 包含一份由 MAP 所建立的記憶體空間配置
- CHECKSUMS: 包含在程序中使用的 checksum 或 CRC。
- PUBLICS: 輸出 public symbol,利用 BY ADDRESS/BY NAME 排序。
- COLUMNS: 輸出 public symbol 的列數 1 or 2。
- WIDTH: 輸出 public symbol 的寬度 80 or 132。
- SYMBOLS: 輸出額外的除錯訊息,比如 local symbol。
- LINES: 輸出行數。
- FILENAME: 設定輸出的檔名,預設值為原始輸入檔案,副檔案改成 .LOC。
Examples 範例
- listfile segments file=test.loc
- listfile publics lines symbols segments
※ MAP
MAP 用來指定某塊記憶體的存取型態。
Syntax: MAP [name] addr TO addr AS memtype
- name: 別名。
- addr: 定義起始位址及終止位址。
- memtype:
- RDONLY: 唯讀。
- RDWR: 可讀可寫。
- RESERVED: 不可存取。
- MMIO: Memory-mapped I/O。
- IRAM: Internal RAM。
- SFR: Special function registers。
Examples 範例
- map my_data 0x00000 to 0x0ffff as rdwr
- map 0x10000 to 0xEFFFF as reserved
※ ORDER
ORDER 用來連結 anchor
Syntax: ORDER anchor_class class_list
Examples 範例
- order DATA BSS STACK
- order DATA BSS
order BSS STACK
※
Syntax:
Examples 範例
※ DEBUG
DEBUG 用來指定那些除錯訊息資料結構要包含在 Intel OMF86 檔案。
Syntax: DEBUG option [option ...]
- IC86:
- NOIC86:
- TYPES:
- NOTYPES:
- PUBLICS
- NOPUBLICS
- SYMBOLS
- NOSYMBOLS
- LINES
- NOLINES
- ALL
Examples 範例
參考文件:C:\Program Files\Paradigm\Docs\locate.pdf。
※ 注意事項
- file 路徑中的反斜線(\)都要用斜線(/)來代替。
- addr 可以是一個 class name 或是 20-bit 的物理位址。
※ ABSFILE
ABSFILE 主要是用來決定是用 integrated debugger 或是採用 Intel OMF86 格式的開發工具。
Syntax: ABSFILE [AXE86|OMF86|NONE] [FORMAT=type] [FILENAME=file]
- AXE86: 選用 integrated debugger 格式,預設輸出副檔名為 .AXE。
- OMF86: 選用 Intel OMF86 格式,預設輸出副檔名為 .ABS。
- NONE: 取消 absolute output file 輸出。
- FORMAT: 用來設定 AXE86 的格式,PD60(Paradigm DEBUG 6.0),PD50(Paradigm DEBUG 5.0),PD40(Paradigm DEBUG 4.0)。
- FILENAME: 用來設定輸出檔案的位置及名稱。
Examples 範例
- absfile omf86 filename=c:\myprog.abs
- absfile axe86 format=pd40
※ CHECKSUM
CHECKSUM 用來計算記憶體區塊的 CRC 值。
Syntax: CHECKSUM addr TO addr [ADDRESS=addr] [FILL=fill] [ROMBIOS|CRC16|CRC32]
- ADDRESS: 用來指定存放 checksum 的物理位置,預設值為記憶體區塊的下一個位址。
- FILL: 用來填滿記憶體區塊未使用到的地方,預設值為 0xFF。
- ROMBIOS: 使用 IBM PC ROM BIOS 計算方法,checksum 1 byte。
- CRC16: 使用 CRC-16 計算方法,checksum 2 bytes。
- CRC32: 使用 CRC-32 計算方法,checksum 4 bytes。
Examples 範例
- checksum 0xc0000 to 0xc07fe fill=0x00 rombios
- checksum 0xf8000 to 0xffffd address=0xffffe crc16
- checksum CODE to ROMDATA crc32
※ CLASS
CLASS 用來指定物理位置到 class 的每一個 segment。
Syntax: CLASS classname = addr16
- addr16: 用來指定 class 的第一個 segment,剩下的 segment 則根據前一個 segment 依序指定物理位置。
Examples 範例
- class CODE = 0xfc00
- class DATA = 0x0040
※ COMPRESS
COMPRESS 用來壓縮重覆的 class,藉此節省空間。
Syntax: COMPRESS classname
- classname: 要被壓縮的 class 名稱,這個 class 必須出現在 DUP 指令中。
Examples 範例
- dup FARDATA ROMFARDATA
compress ROMFARDATA
※ CPUTYPE
CPUTYPE 用來指定微處器的型號。
Syntax: CPUTYPE cpu_id
- cpu_id: Turbo186 - genesis 專用的。
Examples 範例
- cputype turbo186
※ DISPLAY
Syntax: DISPLAY option [option ...]
- NONE: 取消所有診斷顯示。
- FILES: 顯示輸出檔案。
- MODULES: 顯示在輸入檔案找到的模組名稱。
- COMPRESSION: 顯示在壓縮 class 的壓縮統計。
- ALL: 顯示所有的訊息。
Examples 範例
- display files modules
- display none
- display all
※ DUPLICATE
DUPLICATE 用來複製一個 class。一般都是 startup code 用來複製 FLASH 到 RAM。
Syntax: DUPLICATE src_class dest_class
Examples 範例
-
dup DATA ROMDATA // copy class DATA
class DATA = 0x0040 // DATA at 00400H
class CODE = 0xfc00 // CODE at FC000H
order CODE ROMDATA // ROMDATA after CODE
※ HEXFILE
HEXFILE
Syntax: HEXFILE [INTEL80|INTEL86|INTEL386|BINARY|TEKHEX] [OFFSET=addr] [SIZE=size] [SPLIT=split] [FILL=fill] [LENGTH=len] [TRUNCATE] [EOFRECORD|NOEOFRECORD] [ENTRYPOINT|NOENTRYPOINT] [FILENAME=file]
- INTEL80: Intel hex (64KB).
- INTEL86: Intel extended hex (1MB), 預設值.
- INTEL386: Intel 386 extended hex (1MB or 16MB).
- BINARY: Binary (1MB).
- TEKHEX: Tektronix hex (64KB).
- OFFSET: 用來指定開始位址。
- SIZE: 設定 image 的大小,預設值則根據 image type 的最大值來設定,除了 binary 是 32KB。
- SPLIT: 用來分割 image,可分為 1~4 個,預設值是一個,也就是不分割。
- FILL: 在 binary 格式時,用來做未使用的區域填充值,預設值為 0FFH。
- LENGTH: 設定每行記錄有多少 bytes,範圍為 8~64,預設值為 16。
- TRUNCATE: 用來把 binary image 多餘的空白去除,減少 image 的大小。
- EOFRECORD: 設定 end of record 寫入與否,預設是寫入。
- ENTRYPOINT: 設定 entry point record 寫入與否,預設是寫入。
- FILENAME: 用來設定輸出檔案的位置及名稱。
Examples 範例
- hexfile intel80 offset=0xf0000 size=32 file=no1
hexfile intel80 offset=0xf8000 size=32 file=no2
Source Pools 是 node 的集合,用來整理成堆的 source/header files。由於在 .rom 只能新增 node,如果 source file 很多的時候,就變成一團,很難搜尋要修改的檔案。但是 Paradigm 又不援目錄格式,此時就只能靠 SourcePools 來收集 nodes 再丟進 .rom 內,也就是相當於變相的目錄格式。
- Project → New target...
- 輸入 Name,type 選 SourcePool。
- 接著把 test.c 拉到 test[SourcePool](滑鼠移到 test.c,按左鍵不放,移動滑鼠到 test[SourcePool],放開左鍵)。
- 再來先按住 Alt 鍵不放,再把 test[SourcePool] 拉到 test.rom,此時會看到 test.rom 出現粗體字的 test[SourcePool],表示它只是 reference 而已。
- 在原始的 test[SourcePool] add note 會同步出現在 test.rom 的 test[SourcePool],如同 aaa.c,在原始 SourcePool 為原始字體,在 test.rom 的 SourcePool 為粗體字。但是在 test.rom 的 test[SourcePool] add note 是不會同步原始的 test[SourcePool] 喔,如同 bbb.c,新增後為正常字體,表示非 reference 檔案,也沒有在原始 SourcePool 出現。
- 接著 build all,大功告成,三個檔案都有 build 成功。
- 請注意不要把 test[SourcePool] 直接拉到 test.rom 而不做 reference 喔,這樣會造成在 build all 時找不到任何檔案,原因不詳。
- File → New → Project...
- Project Path and Name 輸入你指定的位置,其它的就不用改了。
- 輸入完成按 OK,就會出現下列專案管理視窗。
- 接下來在 test.rom 按右鍵叫出選單,選擇 Add node,就可以新增已存在的檔案。如果要新增一個 c source,則必須先 File → New → Text Edit,然後再 File → Save as... 另存成一個新檔案,再利用 Add node 加進 Project 內。
- 接著 Project → Build all,或是在 test.axe 按右鍵選 Build note 就可以開始編譯,Message 視窗出現 Build process completed,就表示大功告成了。
- 如果要修改一開始專案所指定的 Target,可以在 test.axe 按右鍵叫出選單,再按 TargetExpert...,就會呼叫出 TargetExpert 選單。
pcppug.pdf 寫的
>> plib [@respfile] [option] libname [operations] [, listfile]
執行 PLIB 寫的
>> PLIB libname [/C] [/E] [/P] [/0] commands, listfile
- "+": 新增 OBJ。
- "-": 刪除已存在的 OBJ。
- "*": 還原已存在的 OBJ。
- "+-" or "-+": 替換已存在的 OBJ。
- "*-" or "-*": 還原已存在的 OBJ 並刪除。
examples
- plib mylib +x +y +z
新增 x.obj, y.obj, z.obj 到 mylib.lib。 - plib mylib, mylib.lst
把 mylib.lib 內的所有模組的符號列表輸出到 mylib.lst。 - plib mylib -+x +a -z
替換 x.obj, 新增 a.obj, 刪除 z.obj。 - plib mylib *y, mylib.lst
還原 y.obj 成檔案,並把 mylib.lib 內的所有模組的符號列表輸出到 mylib.lst。
