#include <xc.h> // test.c #include "common.h" // RAMで動かす場合の絶対アドレス範囲は、(0x80005000〜0x80008000)です //__attribute__((address( 0x9D020000 ))) void start_boot(void);//EEPRON使用時 __attribute__((address( 0x80005000 ))) void start_boot(void); void start_boot(){ extern void start_main(); _HANDLES[_IDX_INIT_SUB_FUNC] = start_main;//起動時に動作する関数に、下記start_mainを登録 } //__attribute__((address( 0x9D020400 ))) int wait(int n);//EEPRON使用時 int wait(int n){// nカウント待つ while(n--) { int sw2 = _switch2_state(); //int sw2 = (PORTB & 0x80) == 0; if(sw2 == 1) return 1; // OFFからONに変わった } return 0; } //__attribute__((address( 0x9D020500 ))) void start_main();//EEPRON使用時 void start_main(){ for(;;){ PORTBSET = 0x8000; // D1 LED 点灯(RB15を1):これは、0xbf886128番地への設定です. __asm__ ("NOP"); // チョット待つ if(wait(0x00080000)) break; PORTBCLR = 0x8000; // D1 LED 消灯(RB15を0):これは、0xbf886124番地への設定です. __asm__ ("NOP"); // チョット待つ if(wait(0x00080000)) break; } } RAM上で動作させる場合は、__attribute__((address( 0x80005000 ))) void start_boot(void);の絶対アドレスを 指定していますが、他の絶対アドレス指定は必要がないです。 絶対アドレス指定がなければ、RAM上に配置されます。 そのため、EEPROM上配置した関数では、全て絶対アドレス指定が必要です。 int sw2 = _switch2_state()の代わりに、 int sw2 = (PORTB & 0x80) == 0を利用した場合のコード例を示します。 lui v0,0xbf88 lw v0,0x6120(v0) # v0=0xbf886120 これはPORTB のSFR andi v0,v0,0x80 # v0=PORTB AND 0x80 sltiu v0,v0,1 # if v0 < 1 : v0=1 else v0=0 andi v0,v0,0xff sw v0,16(s8) # int sw2 = 戻り値 ( *(s8+16)をsw2として使う ) lw v1,16(s8) li v0,1 bne v1,v0,LBE2 # if v1 != v0: goto LBE2 nop li v0,1 j LBE21 nop |
#include <xc.h> // test.S (Lチカの無限ループ) .set noreorder #アセンブラに命令の順序を自動変更させない。 .section main_loop,address(0x80005000),code 80005000 <start_boot>: 80005000: 27bdfff8 addiu sp,sp,-8 80005004: afbe0004 sw s8,4(sp) 80005008: 03a0f021 move s8,sp 8000500c: 3c02a000 lui v0,0xa000 80005010: 344240c8 ori v0,v0,0x40c8 80005014: 3c038000 lui v1,0x8000 80005018: 246350b4 addiu v1,v1,20660 8000501c: ac430000 sw v1,0(v0) 80005020: 03c0e821 move sp,s8 80005024: 8fbe0004 lw s8,4(sp) 80005028: 27bd0008 addiu sp,sp,8 8000502c: 03e00008 jr ra 80005030: 00000000 nop 80005034 <wait>: 80005034: 27bdffe0 addiu sp,sp,-32 80005038: afbf001c sw ra,28(sp) 8000503c: afbe0018 sw s8,24(sp) 80005040: 03a0f021 move s8,sp 80005044: afc40020 sw a0,32(s8) 80005048: 08001421 j 80005084 <.LBE2> 8000504c: 00000000 nop 80005050 <.LBB2>: 80005050: 3c02a000 lui v0,0xa000 80005054: 3442401c ori v0,v0,0x401c 80005058: 8c420000 lw v0,0(v0) 8000505c: 0040f809 jalr v0 80005060: 00000000 nop 80005064: afc20010 sw v0,16(s8) 80005068: 8fc30010 lw v1,16(s8) 8000506c: 24020001 li v0,1 80005070: 14620004 bne v1,v0,80005084 <.LBE2> 80005074: 00000000 nop 80005078: 24020001 li v0,1 8000507c: 08001427 j 8000509c <.LBE2+0x18> 80005080: 00000000 nop 80005084 <.LBE2>: 80005084: 8fc20020 lw v0,32(s8) 80005088: 2443ffff addiu v1,v0,-1 8000508c: afc30020 sw v1,32(s8) 80005090: 1440ffef bnez v0,80005050 <.LBB2> 80005094: 00000000 nop 80005098: 00001021 move v0,zero 8000509c: 03c0e821 move sp,s8 800050a0: 8fbf001c lw ra,28(sp) 800050a4: 8fbe0018 lw s8,24(sp) 800050a8: 27bd0020 addiu sp,sp,32 800050ac: 03e00008 jr ra 800050b0: 00000000 nop 800050b4 <start_main>: 800050b4: 27bdffe8 addiu sp,sp,-24 800050b8: afbf0014 sw ra,20(sp) 800050bc: afbe0010 sw s8,16(sp) 800050c0: 03a0f021 move s8,sp 800050c4: 3c02bf88 lui v0,0xbf88 800050c8: 34038000 li v1,0x8000 800050cc: ac436128 sw v1,24872(v0) 800050d0: 00000000 nop 800050d4: 0c00140d jal 80005034 <wait> 800050d8: 3c040008 lui a0,0x8 800050dc: 10400003 beqz v0,800050ec <start_main+0x38> 800050e0: 00000000 nop 800050e4: 08001447 j 8000511c <start_main+0x68> 800050e8: 00000000 nop 800050ec: 3c02bf88 lui v0,0xbf88 800050f0: 34038000 li v1,0x8000 800050f4: ac436124 sw v1,24868(v0) 800050f8: 00000000 nop 800050fc: 0c00140d jal 80005034 <wait> 80005100: 3c040008 lui a0,0x8 80005104: 10400003 beqz v0,80005114 <start_main+0x60> 80005108: 00000000 nop 8000510c: 08001447 j 8000511c <start_main+0x68> 80005110: 00000000 nop 80005114: 08001431 j 800050c4 <start_main+0x10> 80005118: 00000000 nop 8000511c: 03c0e821 move sp,s8 80005120: 8fbf0014 lw ra,20(sp) 80005124: 8fbe0010 lw s8,16(sp) 80005128: 03e00008 jr ra 8000512c: 27bd0018 addiu sp,sp,24 |
以下に、上記の実際に動作した、アセンブリリストを示します。上のC言語の逆アセンブルリストをコードにしてみました。
#include <xc.h> // test.c #include "common.h" int push2=0;// SW2が押されたら1にする変数 // RAMで動かす場合の絶対アドレス範囲は、(0x80005000〜0x80008000)です __attribute__((address( 0x80005000 ))) void start_boot(void); void start_boot(){ extern void start_main(); push2 = _switch2_state(); _HANDLES[_IDX_INIT_SUB_FUNC] = start_main;//起動時に動作する関数に、下記start_mainを登録 } int wait(int n){// nカウント待つ while(n--) { int sw2 = _switch2_state(); if(push2 != sw2){ // エッジ判定 (以前の状態と違うか?) push2 = sw2; // 現状を記憶 if(sw2 == 1) return 1; // OFFからONに変わった } } return 0; } void start_main(){ for(;;){ PORTBSET = 0x8000; // D1 LED 点灯(RB15を1):これは、0xbf886128番地への設定です. __asm__ ("NOP"); // チョット待つ if(wait(0x00080000)) break; PORTBCLR = 0x8000; // D1 LED 消灯(RB15を0):これは、0xbf886124番地への設定です. __asm__ ("NOP"); // チョット待つ if(wait(0x00080000)) break; } }