2016年7月9日 星期六

C語言 - 使用Macro打印除錯訊息

#include <stdio.h>

#define DEBUG

#ifdef DEBUG
#define dprintf(fmt, arg...) \
do { \
        if (debug) \
                printf("DEBUG: " fmt, ##arg); \
        } while (0)
#else
#define dprintf(fmt, arg...)
#endif

int debug = 1;
int main(int argc, char *argv[])
{
        dprintf("%s\n", "hello world");
 
        return 0;
}

執行結果
DEBUG: hello world

2016年7月8日 星期五

C語言 - 使用Macro中#字號用法

1. #: 在Macro展開的時候會將#後面的參數替換成字串

#define dprintf(arg) printf(#arg);

調用dprintf(test)的時候會將#exp換成字串"arg"

2. 程式範例
#include <stdio.h>

#define dprintf(arg) \
do { \

        printf("%s: %s\n", arg, #arg); \
} while (0)

int main(int argc, char *argv[])
{
        char *hello = "DEBUG"; \
        dprintf(hello);
        return 0;
}

執行結果:
DEBUG: hello
3. 上面範例Macro展開後
第一個arg會被hello變數取代,hello是個指標,指向"DEBUG"字串
第二個arg會被"hello"字串取代
dprintf(hello)
do {
        printf("%s: %s\n", hello, "hello");
} while (0)

C語言 - 使用Macro中##字號用法

1. ##: 將前後兩個的單詞拼接在一起

#define show_port(portname) show_##portname

調用show_port(mac0)展開後成為show_mac0

2. 程式範例
#include <stdio.h>

#define show_port(portname, port) \
static void show_##portname() \
{ \
        int val = 0; \
        val |= port; \
        printf("port = %s, ", #portname); \
        printf("val = 0x%04x\n", val); \
}

show_port(mac0, 0);
show_port(mac1, 1);
show_port(cpu, 2);

int main(int argc, char *argv[])
{
        show_mac0();
        show_mac1();
        show_cpu();
 
        return 0;
}
執行結果:
port = mac0, val = 0x0000
port = mac1, val = 0x0001
port = cpu, val = 0x0002
3. Macro展開後
show_port(mac0, 0);展開後
static void show_mac0()
{
    int val = 0;
    val |= 0;

    printf("port = %s, ", "mac0");
    printf("val = 0x%04x\n", val);
}
}
show_port(mac1, 1);展開後
static void show_mac1()
{
    int val = 0;
    val |= 1;

    printf("port = %s, ", "mac0");
    printf("val = 0x%04x\n", val);
}
}
show_port(cpu, 2);展開後
static void show_cpu()
{
    int val = 0;
    val |= 2;

    printf("port = %s, ", "cpu");
    printf("val = 0x%04x\n", val);
}

進階Kernel module的Makefile範例

obj-m := hello.o
ARCH := arm
KRNELDIR := /home/allen/Work/raspberry/linux
CROSS_COMPILE = arm-linux-gnueabihf-
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
PWD := $(shell pwd)
all:
        make -C $(KRNELDIR) M=$(PWD) modules

.PHONY :clean
clean:
        make -C $(KRNELDIR) M=$(PWD) clean

C語言 - Big-endian和Little-endian

1. 範例程式1
#include <stdio.h>

typedef union {
    long l;
    unsigned char c[4];
} Endian;

int main(int argc, char *argv[])
{
    Endian a;
    a.l = 0x12345678;

    if (a.c[0] == 0x78 && a.c[1] == 0x56 &&
        a.c[2] == 0x34 && a.c[3] == 0x12)
        printf("Little endian\n");
    else if (a.c[0] == 0x12 && a.c[1] == 0x34 &&
        a.c[2] == 0x56 && a.c[3] == 0x78)
        printf("Big endian\n");

    printf("a.l = 0x%lx\n", a.l);

    printf("%p: 0x%02x\n", &a.c[0], a.c[0]);
    printf("%p: 0x%02x\n", &a.c[1], a.c[1]);
    printf("%p: 0x%02x\n", &a.c[2], a.c[2]);
    printf("%p: 0x%02x\n", &a.c[3], a.c[3]);
    return 0;
}
執行結果:
Little endian
a.l = 0x12345678
0x7efd9634: 0x78
0x7efd9635: 0x56
0x7efd9636: 0x34
0x7efd9637: 0x12
Ex: long Data=0x12345678,寫到記憶體位址時。
- Big Endian,最高位元組在位址最低位元,最低位元組在位址最高位元,依次排列。

Address   Big-endian
-------------------------------------
0x0000    0x12
0x0001    0x34
0x0002    0x56
0x0003    0x78
-------------------------------------

- Little Endian,最低位元組在最低位元,最高位元組在最高位元,反序排列。
Address   Big-endian
-------------------------------------
0x0000    0x78
0x0001    0x56
0x0002    0x34
0x0003    0x12
-------------------------------------
2. 範例程式2
#include <stdio.h>

int main(int argc, char *argv[])
{
    unsigned int i = 0x00000001;
    char *c = (char *)&i;
 
    if (*c)
        printf("Little endian\n");
    else
        printf("Big endian\n");
 
    return 0;
}
整數宣告中,數值在記憶體中的排列
unsigned int i = 0x00000001;

Address    Big-endian    Little-endian
-------------------------------------
0x0000     0x00          0x01
0x0001     0x00          0x00
0x0002     0x00          0x00
0x0003     0x01          0x00
-------------------------------------


字元宣告中,數值在記憶體中的排列
char *c

Address    Big-endian    Little-endian
-------------------------------------
0x0000     0x00          0x01
-------------------------------------
3. 參考來源
https://zh.wikipedia.org/wiki/%E5%AD%97%E8%8A%82%E5%BA%8F

2016年7月2日 星期六

Raspberry Pi - No space left on device

1. 當安裝完Raspberry Pi官網上的映像檔後,系統上要安裝其它套件時,出現No space left on device的訊息。

2. 執行Raspberry Pi Software Configuration Tools
$ sudo raspi-config
3. 選擇 1. Expand Filesystem,延伸檔案系統大小
4. 選擇Ok,進行下一步
5. 退出後,重新啟動系統
6. 檢查磁碟大小
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        15G  3.4G   11G  25% /
devtmpfs        459M     0  459M   0% /dev
tmpfs           463M     0  463M   0% /dev/shm
tmpfs           463M  6.3M  457M   2% /run
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
tmpfs           463M     0  463M   0% /sys/fs/cgroup
/dev/mmcblk0p1   63M   21M   43M  33% /boot
tmpfs            93M     0   93M   0% /run/user/1000