FastAVRのバグにはいいかげうんざりしたし、アセンブラでプログラムするのも面倒くさすぎるので、Cコンパイラを使ってみる事にしました。WinAVR又はGCCと呼ばれてる、AVR用のCコンパイラをダウンロードして使ってみました。Cって嫌いだったので、今までほとんど触った事がありません。完全な初心者です。

まあ当然いろいろ問題はあったんですが、とりあえず使えるレベルまではたどり着きました。ここでは、初心者として試行錯誤で見つけ事の備忘録です。わかっている人には当たり前の事かもしれません。

使用しているWinAVRはVersion 20070122です。

I was bit sick of programming in assembler,and wanted to move to a compiler. However “FastAVR” Basic compiler is quite useless because of its full of bugs. I looked around for good compilers and end up with “WinAVR” (also called "GCC”). I have not liked C language and never seriously tried before. So I am a complete beginner for C language.

I experienced a lot of trouble with this, but finally my skill reached to an usable level, I hope. I had many cut-and-tries on the way as a beginner. This memorandum includes what I found in struggling with C compiler. Obviously these matters may be commonsense for experts of C.

The version of WinAVR I am using is 20070122.

Programmers Notepadでソースファイルを作るとき、"C/C++"を選んでおくこと。さもないと、"stray error"が出る。

When you create a source file on “Programmers Notepad”, select file type as “C/C++”. Other wise “stray error” may occur. I do not know the meaning of “stray error”.

Indexの使用はできるだけ少なくしたほうがいいようです。Indexのためのコードが非常に大きくなるので、ループのはじめで配列からスカラーに代入し、演算後、ループの終わりにスカラーから配列に戻すことで、コードが節約できます。

Indexing

Indexing consumes lot of object codes. So the use of this should be kept in minimum.

Transfer the members of arrays to scalar s at the start of loops, perform the calculation using scalars, and then store the result to arrays. In this way the object code can be mush smaller.

Variable, ROM data 等の定義を別ファイルとしてMainでIncludeした時、これらのファイルをMakefileでSRC指定をしてはいけない。

#define だけのファイルはSRCしてもOK。

基本的にはSRC指定するのはFunctionのみにする事。

SRC += in Makefile

If definition file of Variables, ROM data, etc. are included in “Main”, do not add these files in “Makefile” using “SRC +=” statements.

Files only with “#define” statements seem OK to add by “SRC +=” statements.

Basically only function files should be add by “SRC +=” statements.

最適化ありで、変数が割り付けられなかったときは、変数をVolatileとする。

Volatileは最適化抑制指定。

基本的には全ての変数をVolatile指定した方がいいと思われる。

If a variable is not allocated after compilation with optimisation, declare that variable as “volatile”.

Varibles with “volatile' declaration will not be a scope of optimisation.

Basically all variables should be declared as “volatile” to prevent roubles.

これは使えないみたい。

*a = *a + 1;

のようにすること。

++ and -- operators can not be used for indirect accessing.

Use:

*a = *a + 1;

instead.

式が長いとき演算結果がおかしくなることあり。実行順序によるオーバーフローと思われる。

*=などを使って、途中オーバーフローが起こらないように分割する事。

In long expressions result of calculation some times gets wrong. It may be caused by overflow in many steps of calculations.

It can be avoided by splitting a long expression into some short expressions considering overflow. For example “*=” type operations may be used.

これは使えないみたい。変なところにアドレスが割り付けられる。

Mainで宣言し、引数で間接渡しとする。

It does not seem work properly. Static variables in sub functions are assigned to funny addresses.

They should be declared in Main and passed to sub functions as indirect address pointer.

アセンブラの場合はリテラルは32ビットインテジャーで計算されますが、GCCでは自動タイプ変換規則が適用されます。このため、以下の例ではすべての計算が16ビットインテジャーで計算されオーバーフローが起こります。

#define literal 8000*1000/16/38400-1
volatile uint16_t test;
test = literal;

これを回避するには、リテラルに対して32ビットインテジャーでキャストすればOKです。例えば、

#define literal (uint32_t)8000*1000/16/38400-1
volatile uint16_t test;
test = literal;

Literals are calculated in 32 bit integer in case of assembler. However in GCC they are calculated following automatic type conversion rule. So following example is calculated as 16 bi integer and an overflow occurs.

#define literal 8000*1000/16/38400-1
volatile uint16_t test;
test = literal;

By casting literal as 32 bit integer the overflow can be avoided. For example:

#define literal (uint32_t)8000*1000/16/38400-1
volatile uint16_t test;
test = literal;

配列のFunctionへの引き渡し

Function Sample


Header Sample

char bin2BCD4(uint16_t,char*);

volatile uint8_t BCD_rpm[4];

BCD_error=bin2BCD4(rpm,&BCD_rpm);

It is very cumbersome to make an interface to functions with arrayed variables in C for Basic programmers like me. Use of POINTER is forced. Arguments in Functions are declared as pointers like (A). Never put [ ] to variable name, or something funny happens. Access to the arrayed variable will be made like (B). Indexing using [ ] can not be used and index should be added to pointer address value.

Basic系の言語を使ってきた人間にとってはこれはやたらに面倒臭い。私の嫌いなポインターの使用を強要されます。Functionの引数は(A)のようにポインターで宣言します。このとき、変数名に[ ]をつけてはいけません。変なことが起こります。アクセスは(B)のようになります。インデックスには[i]みたいなのは使えず、ポインターにインデックスを足すことになります。

When declare fix data in program space in a function, the declaration statement should not be put inside the function as (A). This must be put outside the function.

関数内で固定データをプログラム領域に置くとき、そのデータ宣言文をFunctionの内部(Aの場所)に入れてはいけません。Function外に置きましょう。

#define clock 8000 // CPU Clock (KHz)
#define TC0_prescale 256 // TC0 pre-scale

// statement A
#define AA (int32_t)256*TC0_prescale*1000/clock

// statement B
#define BB (int32_t)1000/AA+1

// statement B'
#define B (int32_t)1000/(int32_t)256*TC0_prescale*1000/clock+1

// statement A'
#define AA ((int32_t)256*TC0_prescale*1000/clock)

// statement B''
#define BB ((int32_t)1000/AA+1)


Be careful if expressions are included in “#define” statements. These statements may give different result from intended. In left example, symbol “AA” defined by “Statement A” is used in “Statement B”. In this case symbol “AA” in “Statement B” is simply replaced by strings in red colour in “Statement A”, giving different expression from intended. If the expressions in #define statements are closed up by paresis's it never happens as Statements A' and B''.

#define に数式を含めるとき注意しないと演算結果が思いもよらないものになります。左の例で、Statement Aで定義した「AA」をStatement Bで使用すると、単に 「AA」が「(int32_t)256*TC0_prescale*1000/clock」に置き換えられるだけなのでStatement B'のように解釈され、意図した計算式になりません。Statement A', B''のように計算式を括弧でくくればOKです。#defineで定義するすべての数式は括弧で括っておくべきでしょう。

ドメインLANに繋がった状態ではGCCのコンパイルは早く(通常2〜3秒)行われますが、LANから切り離された状態ではきっかり10秒余計にかかるという問題がありました。AVR Freaksの掲示板で助けを求めたところ、ネットワークドライブがマップされているとコンパイラがネットワークドライブを探しに行きタイムアウトするまで待つので遅くなるという情報をもらいました。ためしにネットワークドライブを切り離したところ、問題解決。どのネットワークドライブを見に行ってるのかわかりませんので、LANに繋がっていない状態で使うときにこの問題が起こったら、ネットワークドライブをひとつづつ切り離して行けば問題のドライブを確定できると思います。

I had a trouble with compile. It was slow when the computer was disconnected from domain LAN. It took exactly 10 seconds more without connection. I posted a question on AVR Freaks BBS and got a good suggestion. “GCC compiler searches network drives and may wait network time out if the network is not connected.” So I tried to disconnect the network drives and the problem solved. If this problem happened disconnect network drives one by one to identify what drive causes the problem.

AVR StudioからGCCを使う

GCCでコンパイルしてAVR Studioでデバッグしていましたが、馬鹿なことをしていました。AVR StudioからGCCのコンパイルができるのに気がつかなかったのです。

単にプロジェクトとして「AVG GCC」を選べばいいだけであった。Makefileを自動生成してくれ、デバッガーも即起動するので、非常に楽である。

I used to compile the program from GCC and use AVR Studio only for debugging, but I was very silly. I did not notice GCC can be directly used from AVR Studio.

It is done simply choose “AVR GCC” when creating a project. In this case “Makefile” is automatically generated and the debugger starts up straight after compiling.

Variable, ROM data 等の定義を別ファイルとしてMainでIncludeした時、これらのファイルを"Source Files"に登録してはいけない。

基本的には"Source Files"に登録するのはFunctionのみにする事。

この例では"var.c"は変数定義ファイルであり、これが入っているとコンパイルエラーになる。

この"Source Files"は”MakeFile"の"SCR +="と同じ働きをする。

If definition file of Variables, ROM data, etc. are included in “Main”, do not add these files under “Source Files” folder.

Basically only function files should be included in “Source Files” folder. Otherwise compilation would end up with errors.

“Source Files” folder functions as the same way as “SCR +=” in “Makefile”

 


 

 
inserted by FC2 system