天帝
1
STC8A8K64D4を使用しています。公式サイトからソフトウェアをダウンロードしてインストールしましたが、依然として大きな割り込み番号が使用できません。いったい何が問題なのでしょうか?以下にエラー内容を示します。
*** ERROR L121: IMPROPER FIXUP
MODULE: .\Objects\main.obj (MAIN)
OFFSET: 0001C4H
Program Size: data=18.3 xdata=1048 const=0 code=5874
Target not created.
Build Time Elapsed: 00:00:00
ABC
3
ERROR L121: IMPROPER FIXUPというエラーメッセージが表示されていますが、これはKeilでSTCマイコンの大番号割り込み(31を超える場合)を扱う際に非常に典型的な問題です。
簡単に言うと、KeilのC51コンパイラはもともと割り込み番号0~31までしかサポートしていません。あなたが使っているSTC8A8K64D4の場合、UART2・UART3・UART4やPCAなどの割り込み番号が31を超えることが多く、そのまま記述するとこのエラーが発生します。
すでに公式の「割り込み番号拡張ソフト」を使用しているとのことですが、それでもエラーが出るのは、手順が完全に正しく行われていないことが原因です。以下の2つの解決法を紹介します。まずは方法1から試すことをおすすめします(ソフトのインストール済みでも、おそらく呼び出しが正しくできていない可能性が高いです)。
方法1:STC公式「割り込みベクタ番号拡張ツール」を正しく使う
STC-ISPソフトにはこのツールが内蔵されています。「インストールしただけ」で使えるようになるわけではなく、毎回コンパイル前にこのツールを使ってKeilを起動するか、システムファイルを置き換える必要があります。
- ツールを探す:STC-ISPソフトを開き、右側のメニューから「Keil シミュレーション設定」をクリックし、「Keilへ機種とヘッダファイルを追加」というボタンを探します。
- 注意:この操作は単に機種を追加するだけでなく、大番号割り込みに対応するプラグインも自動的に処理してくれます。
- 再度追加する:以前に追加したことがあるかどうかに関わらず、もう一度このボタンをクリックし、Keilのインストール先(例:
C:\\Keil_v5)を選択して追加を確認します。
- プラグインを確認:追加が成功したら、Keilのインストールフォルダにある
\\Keil\\C51\\BIN フォルダを開き、C51.EXEがあるはずです。拡張が成功している場合、STCが大番号割り込みに対応したバージョンのC51.EXEに差し替えまたはパッチが当たっています。
- 再コンパイル:Keilを閉じてプロジェクトを再び開き、Rebuild(Buildではなく)を実行して、エラーが出るかどうか確認します。
方法2:手動でアセンブリジャンプを使う(最も確実な「ハードウェア的」解法)
方法1を試してもエラーが出る場合は、OSの権限などの理由で拡張ツールが正しく動作していない可能性があります。その場合、アセンブリによるジャンプを使うのが最も信頼性が高く、コンパイラのパッチに依存しない方法です。
書き方の例:
元々次のように割り込み関数を書いていたとします(ここでは割り込み番号46と仮定):
void UART4_ISR(void) interrupt 46
{
// 割り込み処理コード
}
以下のように書き換えます:
// 1. 割り込み関数本体:interruptキーワードを使わず、通常の関数として定義
void UART4_ISR(void)
{
// 本来の割り込み処理コード(変更なし)
}
// 2. アセンブリ領域でジャンプを設定:割り込みベクタを上記関数にマッピング
void UART4_ISR_Entry(void) interrupt 46
{
// 組み込みアセンブリで、実際の関数にジャンプ
__asm
LJMP _UART4_ISR
__asm
}
重要なポイント:
- アセンブリ内の関数名には下線をつける:
_UART4_ISR(C関数はコンパイル後、アセンブリ名にアンダースコアが付加されるため)。
LX51リンカーを使用している場合は構文が少し異なりますが、上記の記法はKeil全般で通用します。
まとめと提案
- STC-ISPで「機種とヘッダファイルを追加」を再実行し、パスが正しいか(Keilのルートディレクトリまで選択されているか)確認してください。
- それでもエラーが出る場合は、ツールの再導入にこだわらず、すぐに方法2(アセンブリジャンプ) を使ってください。コードが数行増えるだけで済み、L121エラーは一切出なくなり、移植性も高く、多くのSTC上級者もこの方法を採用しています。
知夏
4
兄弟さん、焦らないでください。STC8シリーズで大きな割り込みを使うときに L121: IMPROPER FIXUP というエラーが出るのは非常によくある問題です。公式の割り込み番号拡張プラグインを使っていても、おそらくKeil内部の設定が追いついていないのが原因です。
以下の最も可能性の高い原因を順に確認してみてください:
1. 拡張リンカー(LX51)に切り替えていない——最も一般的な原因
Keil C51のデフォルトリンカー BL51 は31番以上の大きな割り込みをうまく扱えず、L121エラーを起こしやすくなります。
- 解決方法: Keilの「魔法の杖」アイコン(Targetのオプション)をクリック →
Device タブを開く → Use Extended Linker (LX51) instead of BL51 のチェックボックスをオンにする。その後、「Rebuild All」を実行してみてください。90%のケースでこの対応で問題が即座に解決します。
2. プラグインが間違ったKeilパスにインストールされている
PCに複数のKeilバージョンがインストールされている場合(例えばMDK-ARMとC51が共存している、または別のドライブに別々にインストールされているなど)、公式の拡張パッチが使っていないディレクトリに適用されてしまうことがあります。
- 解決方法: パッチが展開されたパスが、現在使用しているKeilのルートディレクトリであることを確認してください(特に
C51\\BIN フォルダ内のコンパイラファイルが正しく置き換わっているか確認)。
3. Keil C51のバージョンが古すぎる
公式の割り込み番号拡張パッチにはKeilのバージョン要件があります。Keilのバージョンが古すぎると(例:v9.54未満)、パッチを適用しても、下位のアセンブラが大きな割り込みのオフセットアドレスを認識できない可能性があります。
- 解決方法: Keil C51をv9.60以上にアップグレードすることをお勧めします。
4. 編集前の残存ファイルによる影響
パッチ適用後でも、古い .obj ファイルがリンクプロセスを妨害することがあります。
- 解決方法: 「Build」ではなく、「Rebuild All」 をクリックして、古いファイルを完全に削除した上で再コンパイルを行ってください。
まず1番目の手順でLX51への切り替えを試してみてください。それでも解決しない場合は、「魔法の杖」のTargetおよびDeviceタブの画面キャプチャを撮って投稿して確認させてください。