- ベストアンサー
AVRプログラムの関数から戻ってこない
- AtmelStudio6を使用し、ATmega64A向けにプログラムを行っていますが、関数から戻ってこない問題に困っています。
- main()関数では正常に動作するのですが、関数に飛ばすと戻ってこなくなります。
- 問題のプログラムを添付しました。関数test()からの復帰ができない状況です。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
> ちなみに、このプログラムは、CPUを設定して、プロジェクトを作成しただけの > ものに、簡単なサブルーチンを書き足しただけです。 プロジェクトを作成したときにどんなスタートアップが生成されるのか知りませんが... (Atmel Studio 6のIDEは使ったことがないので) > スタックポインタのアドレスなど指定した覚えはないのですが… AVRはリセット時に勝手にスタックポインタが適切な値に設定されることはないはずです。 ツールが生成した(または出来合いの)スタートアップがスタックポインタを設定していないのであれば、RAMの最終番地に設定してください。 具体的な設定方法をドキュメントを読むなりしてください。
その他の回答 (4)
- jacta
- ベストアンサー率26% (845/3158)
スタートアップでスタックポインタにどんな値を設定しているのかを確認してください。 RAMがないところや、普通の変数があるところに設定していれば、まともに動くことはありません。
- jacta
- ベストアンサー率26% (845/3158)
普通に考えると、スタックポインタに正しい値が設定されていないのではないかと思います。 cli()は関数ではなく、インラインアセンブラに展開されるマクロですので、スタック操作は発生しません。 そのために動いているのではないでしょうか?
補足
回答、ありがとうございます。 cli() の件は理解したしました。 アドバイスを参照して、disassembly 窓 で確認したところ、 確かに、不審な動きをしていました。 test() に飛んだアドレスをレジスタに格納している 感じなのですが RET が実行されたら、あらぬアドレスへと飛んでいます。 飛び先が、NOP なので、以降、NOP を実行し続ける状態になっています。 そこで、コンパイルオプションを変更して、AVR Simulator で再コンパイル行い 実行したところ、きちんと動きました。 ただ、これでは、ターゲットCPUに書き込めないので問題解決ではないのですよね… JTAGICE mkII で、コンパイルを行うと、件の症状が発生するのは、ICE かターゲットボード に問題があるのでしょうか?
- hanabutako
- ベストアンサー率54% (492/895)
コンパイルの時に指定したCPUのチップと実際に実行しているチップが一致していないとかでしょうか。アラインメントや命令が微妙に違うために関数呼び出しのあとリターンできていないという状況を想像するのですが。 コンパイルの時のオプションなど様々な設定や、コンパイルでできるアセンブラコードが書いてあるとちょっとは考えるヒントになるかもしれません。
補足
回答 有難うございます。 以下が、elf ファイルです。 上のソースのelfを乗せると、文字数オーバーになるので、問題部分のみ抽出して 作成したelfです。 コンパイルオプションも確かに、怪しいのですが、指定したCPUには間違いはないと 思われます。 問題部分をコメント化すると、正常に動作しますし、デバッグもできます。 関数に飛ぶときに格納したアドレスを見失っている感じがしますが… --------------------------------------- test00.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn 0 .data 00000000 00800100 000000ea 0000015e 2**0 CONTENTS, ALLOC, LOAD, DATA 1 .text 000000ea 00000000 00000000 00000074 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE 2 .stab 000006cc 00000000 00000000 00000160 2**2 CONTENTS, READONLY, DEBUGGING 3 .stabstr 00000085 00000000 00000000 0000082c 2**0 CONTENTS, READONLY, DEBUGGING 4 .debug_aranges 00000080 00000000 00000000 000008b8 2**3 CONTENTS, READONLY, DEBUGGING 5 .debug_info 0000032e 00000000 00000000 00000938 2**0 CONTENTS, READONLY, DEBUGGING 6 .debug_abbrev 0000009f 00000000 00000000 00000c66 2**0 CONTENTS, READONLY, DEBUGGING 7 .debug_line 00000283 00000000 00000000 00000d05 2**0 CONTENTS, READONLY, DEBUGGING 8 .debug_frame 00000034 00000000 00000000 00000f88 2**2 CONTENTS, READONLY, DEBUGGING 9 .debug_str 00000086 00000000 00000000 00000fbc 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00000000 <__vectors>: 0: 0c 94 46 00 jmp 0x8c ; 0x8c <__ctors_end> 4: 0c 94 63 00 jmp 0xc6 ; 0xc6 <__bad_interrupt> 8: 0c 94 63 00 jmp 0xc6 ; 0xc6 <__bad_interrupt> --- 略 --- 88: 0c 94 63 00 jmp 0xc6 ; 0xc6 <__bad_interrupt> 0000008c <__ctors_end>: 8c: 11 24 eor r1, r1 8e: 1f be out 0x3f, r1 ; 63 90: cf ef ldi r28, 0xFF ; 255 92: d0 e1 ldi r29, 0x10 ; 16 94: de bf out 0x3e, r29 ; 62 96: cd bf out 0x3d, r28 ; 61 00000098 <__do_copy_data>: 98: 11 e0 ldi r17, 0x01 ; 1 9a: a0 e0 ldi r26, 0x00 ; 0 9c: b1 e0 ldi r27, 0x01 ; 1 9e: ea ee ldi r30, 0xEA ; 234 a0: f0 e0 ldi r31, 0x00 ; 0 a2: 02 c0 rjmp .+4 ; 0xa8 <__do_copy_data+0x10> a4: 05 90 lpm r0, Z+ a6: 0d 92 st X+, r0 a8: a0 30 cpi r26, 0x00 ; 0 aa: b1 07 cpc r27, r17 ac: d9 f7 brne .-10 ; 0xa4 <__do_copy_data+0xc> 000000ae <__do_clear_bss>: ae: 11 e0 ldi r17, 0x01 ; 1 b0: a0 e0 ldi r26, 0x00 ; 0 b2: b1 e0 ldi r27, 0x01 ; 1 b4: 01 c0 rjmp .+2 ; 0xb8 <.do_clear_bss_start> 000000b6 <.do_clear_bss_loop>: b6: 1d 92 st X+, r1 000000b8 <.do_clear_bss_start>: b8: a0 30 cpi r26, 0x00 ; 0 ba: b1 07 cpc r27, r17 bc: e1 f7 brne .-8 ; 0xb6 <.do_clear_bss_loop> be: 0e 94 68 00 call 0xd0 ; 0xd0 <main> c2: 0c 94 73 00 jmp 0xe6 ; 0xe6 <_exit> 000000c6 <__bad_interrupt>: c6: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> 000000ca <test>: #include <avr/io.h> #include <avr/interrupt.h> void test(void) { DDRA = 0xC0;//ここは。実行される ca: 80 ec ldi r24, 0xC0 ; 192 cc: 8a bb out 0x1a, r24 ; 26 }//ここから、帰ってこない ce: 08 95 ret 000000d0 <main>: int main(void) { cli(); d0: f8 94 cli test();//問題の関数 ここを、コメントにすると問題なく実行 d2: 0e 94 65 00 call 0xca ; 0xca <test> // DDRA = 0xC0;//test()と同じ内容 PORTB = 0xFF; //B出力レジスタ d6: 8f ef ldi r24, 0xFF ; 255 d8: 88 bb out 0x18, r24 ; 24 DDRB = 0xF7; //B方向レジスタ da: 97 ef ldi r25, 0xF7 ; 247 dc: 97 bb out 0x17, r25 ; 23 PORTC = 0xFF; de: 85 bb out 0x15, r24 ; 21 DDRC = 0xDB; e0: 8b ed ldi r24, 0xDB ; 219 e2: 84 bb out 0x14, r24 ; 20 e4: ff cf rjmp .-2 ; 0xe4 <main+0x14> 000000e6 <_exit>: e6: f8 94 cli 000000e8 <__stop_program>: e8: ff cf rjmp .-2 ; 0xe8 <__stop_program>
- papapa0427
- ベストアンサー率25% (371/1472)
大変初心者的な質問で恐縮ですが、関数の最後に「return」の記述はあるのでしょうか?
補足
「return」は、記述していません。 値を返さない場合は、省略可能だと理解しています。 念の為に、「return」 を記述して実行してみましたが、結果は同じでした。 回答、ありがとうございました。
補足
回答ありがとうございます。 仰っている意味は、概ね理解できていると思うのですが、確認方法が解りません。 ATmelStudio のメニューをいろいろと調べてみましたが、アドレス設定らしきものが 解りませんでした。 もしかしたら、コンパイル時にアウトプットしたファイルに書かれているのでしょうか? ちなみに、このプログラムは、CPUを設定して、プロジェクトを作成しただけの ものに、簡単なサブルーチンを書き足しただけです。 スタックポインタのアドレスなど指定した覚えはないのですが…