ってことで その一覧です
通常の宣言 | CMSISでの宣言 | |||
-
|
signed | long | - | int32_t |
- | signed | short | - | int16_t |
- | signed | char | - | int18_t |
- | signed | long | const | const int32_t |
- | signed | short | const | const int16_t |
- | signed | char | const | const int8_t |
volatile | signed | long | - | __O int32_t |
__IO int32_t | ||||
volatile | signed | short | - | __O int16_t |
__IO int16_t | ||||
volatile | signed | char | - | __O int8_t |
__IO int8_t | ||||
volatile | signed | long | const | __I int32_t |
volatile | signed | short | const | __I int 16_t |
volatile | signed | char | const | __I int8_t |
- | unsigned | long | - | uint32_t |
- | unsigned | short | - | uint16_t |
- | unsigned | char | - | uint8_t |
- | unsigned | long | const | const uint32_t |
- | unsigned | short | const | const uint16_t |
- | unsigned | char | const | const uint8_t |
volatile | unsigned | long | - | __O uint32_t |
__IO uint32_t | ||||
volatile | unsigned | short | - | __O uint16_t |
__IO uint16_t | ||||
volatile | unsigned | char | - | __O uint8_t |
__IO uint8_t | ||||
volatile | unsigned | long | const | __I uint32_t |
volatile | unsigned | short | const | __I uint16_t |
volatile | unsigned | char | const | __I uint8_t |
↑の表のように 用途によって 色々と決まりごとがあるみたいです
(excelからコピペしただけなので見づらいですがご了承ください)
もちろん普通のCのようにintとかcharとかboolも可能ですが
この表に従ったほうが環境依存が減るので楽なんだそうです
覚えるのめんどくせーよ…
で ちょっと解説
かなり憶測を含んでるので間違ってたらごめんなさい
まず型の大きさですが
これはint+ビット数で決まります
コンパイラ依存のビットサイズじゃないので
移植が楽だけではなく 読むときにも楽なんだそうです
signed/unsignedですが まぁこれは説明しなくてもわかりますよね
符号あり/なしの区別です
符号ありはint 符号なしはuintです
constは定数か否かみたいな意味合いもありますが
組み込みの場合はRAMかROMかという違いもあります
でもまぁあまり意識することはないと思います
で 問題なのがvolatileっていう国の名前みたいなモノ
これはコンパイラの最適化を無効化するみたいな意味があります
例えば
uint8_t flag = 1;
while(flag) { ... }
というコードがあったて ブロックの中でflagを書き換えていない場合
コンパイラは
while(1) { ... }
と書き換えます
これは「どーせ値が変更されることはないんだから判定するだけムダ」という理由によるものですが
もしかしたらこのflagは割り込みで変更される可能性があるかもしれません
例えばシリアルの送信完了でRESETされる場合
本来は送信が終了されるまで待つだけのはずなのに
実際は無限ループに陥ってしまいます
これを回避するためにvolatileをつけることにより
「この変数は外部から変更されるので強い最適化はしないように」
ということになります
volatileについてはこのページがわかりやすいです
__IOだけでなく__Oも有るのは
コード中から間違って書き換えないように ということだと思います
が __Oを使う用途というのはあまり思いつかない(無いわけではない)
とりあえず こんなところですが
今まではARMでも普通にintとかcharとか使ってたけど
これから少しずつint32_tみたいな書き方に移行していこうかなぁ と 思ったり
volatile、意味が違い増す。これは「壊れやすい」という意味で、外部から書き換えられる可能性があるという宣言です。なので、コンパイラが最適しちゃまずい、ということ(結果的には)になります。ちょっと調べものしていて気になったので。
返信削除