UMEHOSHI ITA TOP PAGE

アセンブリ言語で作る「 LチカをSW2で止める プログラム」

SW2のスイッチは、下記回路図の赤の接続線で示しています。赤マルのRB7に繋がっていますが、 これは制御チップで[PORTB REGISTER]のBit7をを意味しています(資料:DS60001168K TABLE 11-4: PORTB REGISTER MAP)。
SW2のスイッチを押すとこのRB7の入力端子がLowの0になり、 離すとHiの1になります。
このスイッチの状態は、_switch2_state()マクロの戻り値でも取得でき、 押している場合に1、そうでない場合はゼロです。

「リセットスイッチでスタートさせるRAM上で動作するLチカ」のプログラムを こちらのページで紹介していますが、 この点滅をSW2スイッチで止めるプログラムです。 (下記C言語ソースは、「umehoshiEdit」ツールで、ビルド実行できます。
右ソースは逆アセンブルしたコードで、これを参考に、後述のアセンブリソースを作っています。)


#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言語の逆アセンブルリストをコードにしてみました。

(UMEHOSHI ITA基板で使っている制御チップのPIC32MX270F256B用(MIPS32系)アセンブリに必要な情報の概要です。)

以下はint sw2 = _switch2_state()利用コードです。

  上記で編集したアセンブリソースを、左のボタンで「アッセンブル」できます。
番地から実行するUME専用Hexコマンドを、 最後に追加埋め込みする場合にチェックする==>

上記で生成した[UME専用Hexコマンド]のテキストを コピー(CTRL+A CTRL+C)してUMEHOSHI ITAへ転送して動かすことができます。

上記コードを、Pythonで[UMEHOSHI ITA]基板で転送して実行する手順は、 こちらを参照してください。



(以下はint sw2 = (PORTB & 0x80) == 0利用コードです。)

SW2を押した瞬間だけ実行する処理の紹介


#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;
	}
}