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.
|
File Type
Programmers Notepadでソースファイルを作るとき、"C/C++"を選んでおくこと。さもないと、"stray error"が出る。 |
File Type
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”.
|
Indexing
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. |
Makefile の SRC +=
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は最適化抑制指定。
基本的には全ての変数をVolatile指定した方がいいと思われる。 |
Volatile Decralation of Variables
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 -- for Indirect Access
++ and -- operators can not be used for indirect accessing.
Use:
*a = *a + 1;
instead. |
長い式
式が長いとき演算結果がおかしくなることあり。実行順序によるオーバーフローと思われる。
*=などを使って、途中オーバーフローが起こらないように分割する事。 |
Long Expressions
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. |
Sub Function 内の Static変数
これは使えないみたい。変なところにアドレスが割り付けられる。
Mainで宣言し、引数で間接渡しとする。 |
Static Variables in Sub Functions
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; |
Literal Calculation
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*);
Calling from Main volatile uint8_t BCD_rpm[4];
BCD_error=bin2BCD4(rpm,&BCD_rpm); |
Arrayed Variable Interface to a Function
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]みたいなのは使えず、ポインターにインデックスを足すことになります。 |
プログラム領域内のデータ宣言
|
Data Declaration in Program Space
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内の数式
#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)
|
Expressions in #define Statements
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に繋がっていない状態で使うときにこの問題が起こったら、ネットワークドライブをひとつづつ切り離して行けば問題のドライブを確定できると思います。 |
Slow Compile!!
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を自動生成してくれ、デバッガーも即起動するので、非常に楽である。 |
Using GCC from AVR Studio
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. |
AVR Studio (GCC)のソールファイル指定
Variable, ROM data 等の定義を別ファイルとしてMainでIncludeした時、これらのファイルを"Source Files"に登録してはいけない。
基本的には"Source Files"に登録するのはFunctionのみにする事。
この例では"var.c"は変数定義ファイルであり、これが入っているとコンパイルエラーになる。
この"Source Files"は”MakeFile"の"SCR +="と同じ働きをする。 |
Including Source Files in AVR Studio (GCC)
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”
|