コーディング(C言語)
参考
関数
関数プロトタイプ宣言 function prototype declaration 戻り値の型 関数名(引数の型 仮引数名, 引数の型 仮引数名, ...)
int test_func(int test1, int test2) { int sum; sum = test1 + test2; return sum; }
int main() { int goukei; goukei = test_func(1, 2); /*1, 2 は実引数 */ return 0; }
型
- 1byte = 8bit(0x00-0xFF)
CPUのbitと型 コンパイラの定義による
型 16bit 32bit 64bit char 1byte 1byte 1byte short 2byte 2byte 2byte int 2byte 4byte 4byte long 4byte 4byte 8byte long long 8byte 8byte 8byte pointer 2byte 4byte 8byte
構造体
ICのレジスタは構造体で定義して表す
-
レジスタ名 アドレス サイズ SMR 0xff ffb8 1byte BRR 0xff ffb9 1byte SCR 0xff ffba 1byte TDR 0xff ffbb 1byte SSR 0xff ffbc 1byte RDR 0xff ffbd 1byte ソースの書き方
#define SERIAL_SCI_NUM 3 #define H8_3069F_SCI0 ((volatile struct h8_3069f_sci *)0xffffb0) #define H8_3069F_SCI1 ((volatile struct h8_3069f_sci *)0xffffb8) #define H8_3069F_SCI2 ((volatile struct h8_3069f_sci *)0xffffc0) struct h8_3069f_sci { volatile uint8 smr; volatile uint8 brr; volatile uint8 scr; volatile uint8 tdr; volatile uint8 ssr; volatile uint8 rdr; volatile uint8 scmr; }; static struct { volatile struct h8_3069f_sci *sci; } regs[SERIAL_SCI_NUM] = { { H8_3069F_SCI0 }, { H8_3069F_SCI1 }, { H8_3069F_SCI2 }, };
属性
__attribute__((__packed__))
この属性が付いた構造体は詰め物が外され,純粋に構造体のメンバ変数だけで構成されるようになります
構造体のメンバは、メンバの先頭アドレスがバイト境界になるようにパディングが入れられる。
構造体にpackedの属性を追加するとパディングがなくなる。
struct sample_st { char c; // 1byte int n; // 4byte void *p; // 8byte }; struct sample_st_packed { char c; // 1byte int n; // 4byte void *p; // 8byte } __attribute__ ((packed)); struct sample_st_nopad { char c; // 1byte unsigned char pad1[3]; int n; // 4byte void *p; // 8byte };
sample_st
address data memo 0 C cは1byte. Cとn合わせて4byteになるように
3byteがパディングされている4 n 8 p sample_st_packed
address data memo 0 c 1 n cとnのメンバの間がパディングされていない 5 p sample_st_nopad
address data memo 0 c 1 pad cとpad[3]で4byteになるように手動でパディング追加 4 n 8 p
共用体
union sample_un { unsigned char reg; struct bits { unsigned char bit0:1; unsigned char bit1:1; unsigned char bit2:1; unsigned char bit3:1; unsigned char bit4:1; unsigned char bit5:1; unsigned char bit6:1; unsigned char bit7:1; } regbit; };
同じアドレスに配置される
ICのレジスタで1byteのアドレスのbit毎に機能が付加されている場合などに使用できる- 例 ポートデータレジスタ
マイコンのGPIOのデータを制御するレジスタ
bit毎にportの出力データを設定できる
GPIO P17 pinをHighにしたい場合は、
address0の7bit目を1に設定reg.bi7 = 0x1;
もしくは、reg = reg & 0x80;
address bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 0 P17 P16 P15 P14 P13 P12 P11 P10 - 例 ポートデータレジスタ
マイコンのGPIOのデータを制御するレジスタ
プリプロセッサ
キーワード | 説明 | 例 |
---|---|---|
# | 何もしない | |
#if, #ifdef | 条件分として使う | |
#ifndef,#elif | 条件分として使う | |
#else, #endif | 条件分として使う | |
#include | ヘッダファイルを取り込む | |
#define | マクロを定義する | |
#undef | マクロの定義を無効化する | |
## | 前後の文字を連結する | #define ___concat(a, b) a ## b |
__DATE__ | コンパイルの日にち | |
__TIME__ | コンパイル時の時刻 | |
__FILE__ | ソースファイル名 | printf("%s %s \n", __func__, __FILE__); |
__LINE__ | 行番号 |
- ##の例
/* components/firmware/uboot/arch/arc/include/asm/io.h */ #define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) #define clrsetbits(type, addr, clear, set) \ out_##type((addr), (in_##type(addr) & ~(clear)) | (set)) #define out_le32(a, v)» out_arch(l, le32, a, v) #define out_arch(type, endian, a, v) __raw_write##type(cpu_to_##endian(v), a) #define __raw_writel(v, c) ({ __iowmb(); __arch_putl(v, c); }) /* マクロが続く */
C言語のプログラムの始まりと終わり
- GCCプロジェクトで変数や関数を指定のセクションに配置する方法
変数や関数の宣言文に、attributeキーワードで配置先のセクション名を指定すると、指定されたセクションに変数や関数が配置されます。
たとえば変数myVar[ ]を .mydata セクションに配置するには以下のように記述します。
char myVar[32] __attribute__ ((section (".mydata"))) = { ...
同様に、宣言にattributeを付けることで、関数のコードを指定のセクションに置くことができます。
また、1つのソースファイル内のデータ/コードセクションを一括して特定のセクションに配置する方法もあります。
#include <stdio.h> #include <stdlib.h> int count = 0; void init1() { count++; printf("ctors test. (init1)\n"); } void init2() { count++; count++; printf("ctors test. (init2)\n"); } void fini1() { printf("dtors test. (fini1)\n"); } void fini2() { printf("dtors test. (fini2)\n"); } void fini3() { printf("atexit test. (fini3)\n"); } void (*fp1) (void) __attribute__((section(".ctors"))) = init1; void (*fp2) (void) __attribute__((section(".ctors"))) = init2; void (*fp3) (void) __attribute__((section(".dtors"))) = fini1; void (*fp4) (void) __attribute__((section(".dtors"))) = fini2; int main() { atexit(fini3); printf("%d\n", count); exit (0); printf("never\n"); }
$ clang ctors.c $ ./a.out ctors test. (init2) ctors test. (init1) 3 atexit test. (fini3) dtors test. (fini1) dtors test. (fini2)
ctorsはconstructors、dtorsはdestructors
.ctors C++用グローバルコンストラクタテーブルのセクション
.dtors C++用グローバルデストラクタテーブルのセクション