概要 |
C8051F005において、CPUのバグと思われる現象を発見しました。 このバグは、レジスタバンク切替とレジスタバンクの操作に関連するものです。 |
サンプルプログラム |
このプログラムはC8051F005を搭載した評価用キットC8051005DK-J上で動作する試験プログラムです。 かならずled_on:が実行されるよう記述してあります。led_blink:が実行されることはありません。 しかし、プログラムを実機で動作させるとled_onではなくled_blinkを実行します。 Cygnal
IDE
Ver1.85のJTAGデバッガによるステップ/トレース実行時にはled_onを実行します。 プログラムの動作を追跡した結果、17行目の実行時に直前のレジスタバンク変更が反映されていないことが判りました。
| |
行 |
ラベル |
アセンブラコード |
コメント |
ステップ実行時 |
実機動作時 |
| a |
R0 |
00h |
08h |
a |
R0 |
00h |
08h |
| 定義 |
1 |
|
XBR2 DATA 0E3H |
デジタルクロスバ設定レジスタ |
|
|
| 2 |
|
WDTCN DATA 0FFH |
WDT設定レジスタ |
| 3 |
|
PRT1CF DATA 0A5H |
Port 1入出力方向設定レジスタ |
| 4 |
|
P1 DATA 090H |
Port 1レジスタ |
| 5 |
|
PSW DATA 0D0H |
Program Status Word |
| 初期設定 |
6 |
|
code at 0000h |
リセットベクタ 0h |
| 7 |
start: |
mov XBR2, #40h |
クロスバ初期設定 |
| 8 |
|
orl PRT1CF,#01000000b |
P1.6を出力に設定 |
| 9 |
|
setb P1.6 |
LED点燈 |
| 10 |
|
mov WDTCN, #0DEh |
WDT禁止の標準手順 |
| 11 |
|
mov WDTCN, #0ADh |
| 主処理 |
12 |
|
mov psw,#00h |
レジスタバンク = 0 |
- |
- |
- |
- |
- |
- |
- |
- |
| 13 |
|
clr, a |
a = 0h |
00 |
- |
- |
- |
00 |
- |
- |
- |
| 14 |
|
mov r0,#55h |
R0 = 55h |
00 |
55 |
55 |
- |
00 |
55 |
55 |
- |
| 15 |
|
mov psw,#08h |
レジスタバンク = 1 |
00 |
55 |
55 |
- |
00 |
55 |
55 |
- |
| 16 |
|
mov psw,#00h |
レジスタバンク = 0 |
00 |
55 |
55 |
- |
00 |
55 |
55 |
- |
| 17 |
|
mov r0, a |
R0 = A |
00 |
00 |
00 |
- |
00 |
55 |
55 |
00 |
| 判定 |
18 |
|
mov a,r0 |
a = R0 |
00 |
00 |
00 |
- |
55 |
55 |
55 |
00 |
| 19 |
|
jz led_on |
if(a == 0)jmp led_on |
00 |
00 |
00 |
- |
55 |
55 |
55 |
00 |
| 終端処理 |
20 |
led_blink: |
djnz R5, led_blink |
LED点滅 |
|
点滅 |
| 21 |
|
djnz R6, led_blink |
| 22 |
|
cpl P1.6 |
| 23 |
|
jmp led_blink |
| 24 |
led_on: |
jmp led_on |
LED点燈 |
点燈 |
|
| |
25 |
|
END |
|
|
|
- 00h はレジスタバンク0のR0
- 08h はレジスタバンク1のR0
- 14行目でAレジスタに保存する値は0以外であれば良く、「55」でなくてもよい
| |
レジスタバンク変更のタイミング
|
17行と18行の間にmov Rn,a命令を挿入して実験した結果、2回目のmov
Rn,a命令ではレジスタバンク変更が反映されていることを確認しました。
| |
行 |
アセンブラコード |
コメント |
ステップ実行時 |
実機動作時 |
| a |
R0 |
00h |
08h |
a |
R0 |
00h |
08h |
| 主処理 |
12 |
mov psw,#00h |
レジスタバンク = 0 |
- |
- |
- |
- |
- |
- |
- |
- |
| 13 |
clr, a |
a = 0h |
00 |
- |
- |
- |
00 |
- |
- |
- |
| 14 |
mov r0,#55h |
R0 = 55h |
00 |
55 |
55 |
- |
00 |
55 |
55 |
- |
| 15 |
mov psw,#08h |
レジスタバンク = 1 |
00 |
55 |
55 |
- |
00 |
55 |
55 |
- |
| 16 |
mov psw,#00h |
レジスタバンク = 0 |
00 |
55 |
55 |
- |
00 |
55 |
55 |
- |
| 17 |
mov r0, a |
R0 = A |
00 |
00 |
00 |
- |
00 |
55 |
55 |
00 |
| ★ |
mov r0, a |
R0 = A |
00 |
00 |
00 |
- |
00 |
00 |
00 |
00 |
| 判定 |
18 |
mov a,r0 |
|
00 |
00 |
00 |
- |
00 |
00 |
00 |
00 |
| 19 |
jz led_on |
if(a == 0)jmp led_on |
00 |
00 |
00 |
- |
00 |
00 |
00 |
00 | さらに16行と17行の間にnopを挿入して実験した結果、プログラムが記述通りに実行することを確認しました。
| |
行 |
アセンブラコード |
コメント |
ステップ実行時 |
実機動作時 |
| a |
R0 |
00h |
08h |
a |
R0 |
00h |
08h |
| 主処理 |
12 |
mov psw,#00h |
レジスタバンク = 0 |
- |
- |
- |
- |
- |
- |
- |
- |
| 13 |
clr, a |
a = 0h |
00 |
- |
- |
- |
00 |
- |
- |
- |
| 14 |
mov r0,#55h |
R0 = 55h |
00 |
55 |
55 |
- |
00 |
55 |
55 |
- |
| 15 |
mov psw,#08h |
レジスタバンク = 1 |
00 |
55 |
55 |
- |
00 |
55 |
55 |
- |
| 16 |
mov psw,#00h |
レジスタバンク = 0 |
00 |
55 |
55 |
- |
00 |
55 |
55 |
- |
| ★ |
nop |
|
00 |
00 |
00 |
- |
00 |
00 |
00 |
- |
| 17 |
mov r0, a |
R0 = A |
00 |
00 |
00 |
- |
00 |
00 |
00 |
- |
| 判定 |
18 |
mov a,r0 |
|
00 |
00 |
00 |
- |
00 |
00 |
00 |
- |
| 19 |
jz led_on |
if(a == 0)jmp led_on |
00 |
00 |
00 |
- |
00 |
00 |
00 |
- | この2点から、レジスタバンクの変更がmov
Rn,a命令の実行に反映されるまでに、レジスタバンク変更後1命令以上経過した後であることを確認しました。。 |
バンク切替の試験
|
特定のレジスタバンク特有の問題であるかどうかを確認するために、初期レジスタバンクと一時変更先レジスタバンクのすべての組み合わせ(4バンク×4バンク=16通り)を試験した結果、以下のことを確認しました。
- どのバンクからどのバンクへの変更でも構わない。
- 同一バンクへの変更ではいけない(それは変更ではない)
|
Rnレジスタの試験
|
特定のRnレジスタの問題であるかどうかを確認するために、14行と17行のRnをR0〜R7に設定して試験した結果、特定のRnレジスタ特有の問題ではないことを確認しました。 なお、初期レジスタバンク0で試験を実施しました。他のレジスタバンクでは未試験です。 |
レジスタバンク参照命令の試験
|
すくなくともレジスタバンク変更直後のmov
Rn,a命令実行時にはレジスタバンク変更の効果が得られないことがわかっているが、その他のレジスタバンクを参照する命令が正常に動作するかどうかを確認した。 C8051ではレジスタバンクを参照する命令は以下に示す31命令であり、
17行の実行時に直前のレジスタバンク変更が反映されない条件として、以下を確認ました。
- mov Rn,a命令であること。
- 17行でレジスタバンクを変更すること
- どのバンクからどのバンクへの変更でも構わない。
- 同一バンクへの変更ではいけない
- 16行と17行の間にnopがあってはいけない
| 分類 |
|
ニーモニック |
オペランド |
機能 |
結果 |
| 算術演算 |
1 |
ADD |
A,Rn |
A ← A + Rn |
|
| 2 |
ADD |
@Ri |
A ← A + (Ri) |
|
| 3 |
ADDC |
A,Rn |
A ← A + Rn + Carry |
|
| 4 |
ADDC |
@Ri |
A ← A + (Ri) + Carry |
|
| 5 |
SUBB |
A,Rn |
A ← A - Rn - Borrw |
|
| 6 |
SUBB |
@Ri |
A ← A - (Ri) - Borrow |
|
| 7 |
INC |
Rn |
Rn ← Rn + 1 |
|
| 8 |
INC |
@Ri |
(Ri) ← (Ri) + 1 |
|
| 9 |
DEC |
Rn |
Rn ← Rn - 1 |
|
| 10 |
DEC |
@Ri |
(Ri) ← (Ri) - 1 |
|
| 論理演算 |
11 |
ANL |
A,Rn |
A ← A .OR. Rn |
|
| 12 |
ANL |
@Ri |
A ← A .OR. @Ri |
|
| 13 |
ORL |
@Ri |
A ← A OR @Ri |
|
| 14 |
XRL |
A,Rn |
A ← A .XOR. Rn |
|
| 15 |
XRL |
@Ri |
A ← A .XOR. @Ri |
|
| データ転送 |
16 |
MOV |
A,Rn |
A ← Rn |
OK |
| 17 |
MOV |
A,@Ri |
A ← @Ri |
|
| 18 |
MOV |
Rn,A |
Rn ← A |
NG |
| 19 |
MOV |
Rn,direct |
Rn ← (direct) |
|
| 20 |
MOV |
Rn,#data |
Rn ← data |
|
| 21 |
MOV |
direct,Rn |
(direct) ← Rn |
|
| 22 |
MOV |
direct,@Ri |
(direct) ← @Ri |
|
| 23 |
MOV |
@Ri,A |
Ri ← A |
|
| 24 |
MOV |
@Ri,direct |
Ri ← (direct) |
|
| 25 |
MOV |
@ri,#data |
Ri ← data |
|
| 26 |
MOVX |
A,@Ri |
A ← Ri |
|
| 27 |
MOVX |
@Ri,A |
Ri ← A |
|
| 28 |
XCH |
A,Rn |
A xch Rn |
|
| 29 |
XCH |
A,direct |
A xch (direct) |
|
| 30 |
XCH |
A,@Ri |
A xch Ri |
|
| プログラム分岐 |
31 |
DJNZ |
Rn,rel |
DEC Rn, Jump if (Rn <> 0) |
| |
考察
|
|