電子書籍の厳選無料作品が豊富!

AtmelStudio6 で、ATmega64A向けにプログラム行なっているのですが、
すごく、単純なところで困っています。
ICEは、AVR JTAGICE です。

main() のみで処理をさせると普通に動くのですが、関数に飛ばすと飛んだ先の
関数から戻ってこなくなるのです。
ツールかレジスタの設定が不十分なのかもしれません。

-- 問題のプログラム --

#include <avr/io.h>
#include <avr/iom64a.h>
#include <avr/interrupt.h>
#include <util/delay.h>



void test(void){

DDRA = 0xC0;//<ここは、実行される

}//デバッガで見ると、ここで止まっている。

int main(void)
{
cli();//この関数はライブラリにあるので戻ってくる

test();//この関数から帰ってこない

//DDRA = 0xC0; //test();の内容をここに書くと、正常に処理して通過する。

PORTB = 0xFF;//B出力レジスタ
DDRB = 0xF7;//B方向レジスタ
PORTC = 0xFF;
DDRC = 0xDB;


while(1)
{

//TODO:: Please write your application code

LEDを点滅させるプログラム <略>

}
}

-------------------------------------------------------

何方か心当たりのある方は居ないでしょうか?

A 回答 (5件)

> ちなみに、このプログラムは、CPUを設定して、プロジェクトを作成しただけの


> ものに、簡単なサブルーチンを書き足しただけです。

プロジェクトを作成したときにどんなスタートアップが生成されるのか知りませんが...
(Atmel Studio 6のIDEは使ったことがないので)

> スタックポインタのアドレスなど指定した覚えはないのですが…

AVRはリセット時に勝手にスタックポインタが適切な値に設定されることはないはずです。
ツールが生成した(または出来合いの)スタートアップがスタックポインタを設定していないのであれば、RAMの最終番地に設定してください。
具体的な設定方法をドキュメントを読むなりしてください。
    • good
    • 0

スタートアップでスタックポインタにどんな値を設定しているのかを確認してください。


RAMがないところや、普通の変数があるところに設定していれば、まともに動くことはありません。

この回答への補足

回答ありがとうございます。
仰っている意味は、概ね理解できていると思うのですが、確認方法が解りません。

ATmelStudio のメニューをいろいろと調べてみましたが、アドレス設定らしきものが
解りませんでした。

もしかしたら、コンパイル時にアウトプットしたファイルに書かれているのでしょうか?

ちなみに、このプログラムは、CPUを設定して、プロジェクトを作成しただけの
ものに、簡単なサブルーチンを書き足しただけです。
スタックポインタのアドレスなど指定した覚えはないのですが…

補足日時:2013/01/05 02:17
    • good
    • 1

普通に考えると、スタックポインタに正しい値が設定されていないのではないかと思います。



cli()は関数ではなく、インラインアセンブラに展開されるマクロですので、スタック操作は発生しません。
そのために動いているのではないでしょうか?

この回答への補足

回答、ありがとうございます。
cli() の件は理解したしました。

アドバイスを参照して、disassembly 窓 で確認したところ、
確かに、不審な動きをしていました。

test() に飛んだアドレスをレジスタに格納している 感じなのですが
RET が実行されたら、あらぬアドレスへと飛んでいます。

飛び先が、NOP なので、以降、NOP を実行し続ける状態になっています。


そこで、コンパイルオプションを変更して、AVR Simulator で再コンパイル行い
実行したところ、きちんと動きました。
ただ、これでは、ターゲットCPUに書き込めないので問題解決ではないのですよね…


JTAGICE mkII で、コンパイルを行うと、件の症状が発生するのは、ICE かターゲットボード
に問題があるのでしょうか?

補足日時:2013/01/04 20:57
    • good
    • 0

コンパイルの時に指定した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 jmp0x8c; 0x8c <__ctors_end>
4:0c 94 63 00 jmp0xc6; 0xc6 <__bad_interrupt>
8:0c 94 63 00 jmp0xc6; 0xc6 <__bad_interrupt>
--- 略 ---
88:0c 94 63 00 jmp0xc6; 0xc6 <__bad_interrupt>

0000008c <__ctors_end>:
8c:11 24 eorr1, r1
8e:1f be out0x3f, r1; 63
90:cf ef ldir28, 0xFF; 255
92:d0 e1 ldir29, 0x10; 16
94:de bf out0x3e, r29; 62
96:cd bf out0x3d, r28; 61

00000098 <__do_copy_data>:
98:11 e0 ldir17, 0x01; 1
9a:a0 e0 ldir26, 0x00; 0
9c:b1 e0 ldir27, 0x01; 1
9e:ea ee ldir30, 0xEA; 234
a0:f0 e0 ldir31, 0x00; 0
a2:02 c0 rjmp.+4 ; 0xa8 <__do_copy_data+0x10>
a4:05 90 lpmr0, Z+
a6:0d 92 stX+, r0
a8:a0 30 cpir26, 0x00; 0
aa:b1 07 cpcr27, r17
ac:d9 f7 brne.-10 ; 0xa4 <__do_copy_data+0xc>

000000ae <__do_clear_bss>:
ae:11 e0 ldir17, 0x01; 1
b0:a0 e0 ldir26, 0x00; 0
b2:b1 e0 ldir27, 0x01; 1
b4:01 c0 rjmp.+2 ; 0xb8 <.do_clear_bss_start>

000000b6 <.do_clear_bss_loop>:
b6:1d 92 stX+, r1

000000b8 <.do_clear_bss_start>:
b8:a0 30 cpir26, 0x00; 0
ba:b1 07 cpcr27, r17
bc:e1 f7 brne.-8 ; 0xb6 <.do_clear_bss_loop>
be:0e 94 68 00 call0xd0; 0xd0 <main>
c2:0c 94 73 00 jmp0xe6; 0xe6 <_exit>

000000c6 <__bad_interrupt>:
c6:0c 94 00 00 jmp0; 0x0 <__vectors>

000000ca <test>:
#include <avr/io.h>
#include <avr/interrupt.h>

void test(void)
{
DDRA = 0xC0;//ここは。実行される
ca:80 ec ldir24, 0xC0; 192
cc:8a bb out0x1a, r24; 26

}//ここから、帰ってこない
ce:08 95 ret

000000d0 <main>:


int main(void)
{
cli();
d0:f8 94 cli

test();//問題の関数 ここを、コメントにすると問題なく実行
d2:0e 94 65 00 call0xca; 0xca <test>

//DDRA = 0xC0;//test()と同じ内容
PORTB = 0xFF;//B出力レジスタ
d6:8f ef ldir24, 0xFF; 255
d8:88 bb out0x18, r24; 24
DDRB = 0xF7;//B方向レジスタ
da:97 ef ldir25, 0xF7; 247
dc:97 bb out0x17, r25; 23
PORTC = 0xFF;
de:85 bb out0x15, r24; 21
DDRC = 0xDB;
e0:8b ed ldir24, 0xDB; 219
e2:84 bb out0x14, 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>

補足日時:2013/01/03 20:59
    • good
    • 0

大変初心者的な質問で恐縮ですが、関数の最後に「return」の記述はあるのでしょうか?

この回答への補足

「return」は、記述していません。
値を返さない場合は、省略可能だと理解しています。

念の為に、「return」 を記述して実行してみましたが、結果は同じでした。

回答、ありがとうございました。

補足日時:2013/01/03 17:28
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!