Windows 7でKeil uVison 4を使用するstm32f105のcプロジェクトで非常に奇妙な動作が見られます。私はデバッガでそれをチェックし、数時間後にエラーを追跡した後に、他のプロジェクトの関数ですでにテストされているエラーから、エラーをローカライズしました。そのように見えたのは:STM32f105 BLT命令はローカル変数を再配置します
uint8_t can_add_filter_mask(can_t* this, uint32_t id, uint32_t id_mask, can_frm_type_t type, can_frm_type_t type_mask)
{
CAN_FilterInitTypeDef filt;
/* Empty filter available? */
if(this->filter_len >= 14)
{
return FALSE;
}
/* Select filter number */
if(this->canx == CAN1)
filt.CAN_FilterNumber = this->filter_len + 0;
else
filt.CAN_FilterNumber = this->filter_len + 14;
this->filter_len++;
...
//filt is read
CAN_FilterInit(&filt);
}
構造体filtは、いずれのアサイメントの後でも変更されていないようになっていました。その後、私はdissassemblyを変更し、それは次のようだ(私はそれがだとごめんなさいビット長):
108: uint8_t can_add_filter_mask(can_t* this, uint32_t id, uint32_t id_mask, can_frm_type_t type, can_frm_type_t type_mask)
0x08001B22 BD70 POP {r4-r6,pc}
109: {
110: CAN_FilterInitTypeDef filt;
111:
112: /* Empty filter available? */
0x08001B24 E92D41FF PUSH {r0-r8,lr}
0x08001B28 4604 MOV r4,r0
0x08001B2A 460D MOV r5,r1
0x08001B2C 4690 MOV r8,r2
0x08001B2E 461E MOV r6,r3
0x08001B30 9F0A LDR r7,[sp,#0x28]
113: if(this->filter_len >= 14)
114: {
0x08001B32 7C20 LDRB r0,[r4,#0x10]
0x08001B34 280E CMP r0,#0x0E
0x08001B36 DB03 BLT 0x08001B40
115: return FALSE;
0x08001B38 2000 MOVS r0,#0x00
151: }
152:
153: /******************************************************************************/
154: void can_clr_filter(can_t* this)
0x08001B3A B004 ADD sp,sp,#0x10
0x08001B3C E8BD81F0 POP {r4-r8,pc}
119: if(this->canx == CAN1)
0x08001B40 4970 LDR r1,[pc,#448] ; @0x08001D04
0x08001B42 6820 LDR r0,[r4,#0x00]
0x08001B44 4288 CMP r0,r1
0x08001B46 D103 BNE 0x08001B50
120: filt.CAN_FilterNumber = this->filter_len + 0;
121: else
0x08001B48 7C20 LDRB r0,[r4,#0x10]
0x08001B4A F88D000A STRB r0,[sp,#0x0A]
0x08001B4E E004 B 0x08001B5A
122: filt.CAN_FilterNumber = this->filter_len + 14;
0x08001B50 7C20 LDRB r0,[r4,#0x10]
0x08001B52 300E ADDS r0,r0,#0x0E
0x08001B54 B2C0 UXTB r0,r0
0x08001B56 F88D000A STRB r0,[sp,#0x0A]
123: this->filter_len++;
124:
125: /* Select mask mode */
0x08001B5A 7C20 LDRB r0,[r4,#0x10]
0x08001B5C 1C40 ADDS r0,r0,#1
0x08001B5E 7420 STRB r0,[r4,#0x10]
私は組み立ての専門家で、どちらもARMの専門家ではないんだけど、私はアセンブリ上のビットをプログラミングされています私には悪くはない。私が気付いたのは少し間違っていたことが間には別の関数can_clr_filterの一部であったため、コンパイラがいくつかのコードを再利用していたように見えましたが、最適化はすべてオフになっていました。興味深い部分は、私がfilt.CAN_FilterNumber
変数のアドレスをチェックすると、それは0x20002252に対処するためのアドレス0x20002262からライン
0x08001B36 DB03 BLT 0x08001B40
後に変更されたことでした。だから、すべての変更はメモリ内の他の場所に適用されました!!変数が静的であると宣言した後、問題は消えてしまいました。実際に何が起こったのかは私には分かりません...命令BLTによってローカル変数が別のアドレスに再配置されることはどうですか?または、& filt.CAN_FilterNumberを見て、uVisionデバッガが誤った参照値を表示する可能性がありますか?
「this」が「NULL」ではないことを確認してから、有効なアドレスを指していますか?スタックオーバーフローの危険性はありますか?つまり、現在のタスクのスタック内にどこに場所があり、余裕があるのですか? 'BLT'自体はスタックを使うべきではありませんが、もしあなたがすでに奇妙なことが起こっているかもしれません。 – unwind
@unwind、しました。 'this-> canx'はグローバル変数CAN2と同じアドレスを持っているため、 'this'はすでに完全に初期化されていたため、 'this'は 'NULL'ではありません。スタックは1KB大きいです。それはもちろん問題かもしれません。それを見つける方法? –
@judoka_aclは、スタックオーバーフローを排除するために、いくつかの '0xdeadf00d'ワードのように、割り当てられたスタックメモリの一番下にカナリアの値を置き、次にカナリアが生きているかどうかをチェックします。初期値)。スタックが割り当てられた領域から大きくなると、カナリアの値も上書きされます(原点を見つけることは困難です)。コンパイラの中には、デバッグビルドのための類似の/より良いテクニックを提供し、あらゆる関数呼び出しのまわりでスタックの有効性をチェックするものもありますが、簡単なマニュアルカナリアはプロダクションビルドであっても十分に高速です。 – Ped7g