240221

Yonggeun Park·2024년 2월 21일
0

개발 환경 점검
samba, nfs를 사용하기 위해 SD카드를 빼서 다시 이미지를 받아야한다

$ locate
를 이용해서 찾는다

홈 디렉토리의

이것이고

용량은 이정도 된다

우분투와 SD카드를 연결하고

$ df 

명령어로

마운트 되었는지 확인한다

~$ sudo umount /dev/sdb?

이제 write 해보자

~$ sudo dd if=sdimage.img of=/dev/sdb bs=1M status=progress

if : input file
of : output file
bs : block size
status progress : 현재 상태 출력

다 쓰여졌으면 라즈베리파이를 킨다
근데 커널 버전이 다르기 때문에 업데이트는 해줘야 한다

~$ sudo apt install crossbuild-essential-armhf
~$ cd pi_bsp/kernel/linux
~/pi_bsp/kernel/linux$ ./build.sh


다시 SD카드를 우분투에 마운트 하고
df로 둘 다 있는지 확인한다

이제 커널 설치를 한다

~/pi_bsp/kernel/linux$ sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=/media/ubuntu/rootfs modules_install

~/pi_bsp/kernel/linux$ sudo cp /media/ubuntu/bootfs/kernel7l.img /media/ubuntu/bootfs/kernel7l-backup.img

~/pi_bsp/kernel/linux$ sudo cp arch/arm/boot/zImage /media/ubuntu/bootfs/kernel7l.img

~/pi_bsp/kernel/linux$ sudo cp arch/arm/boot/dts/*.dtb /media/ubuntu/bootfs/

~/pi_bsp/kernel/linux$ sudo cp arch/arm/boot/dts/overlays/*.dtb* /media/ubuntu/bootfs/overlays/

~/pi_bsp/kernel/linux$ sudo cp arch/arm/boot/dts/overlays/README /media/ubuntu/bootfs/overlays/

~/pi_bsp/kernel/linux$ sudo vi /media/ubuntu/bootfs/config.txt    
//제일 아래 추가
------------
arm_64bit=0
------------

완료 후 SD카드를 다시 한번 라즈베리파이에 연결하면 잘 부팅이 된다!

~$ uname -a      // 커널 버전 확인 6.1.77
~$ lsmod         // 모듈들 확인(없으면 커널 설치부터 다시 한다)

$ df 
하면 /dev/mmcblk0p2가 7기가만 있기 때문에 늘릴 것이다

$ sudo raspi-config
6 Advanced...-A1
reboot한다

하고 나면

잘 늘어나 있다

디바이스 드라이버와 관련된 책은
https://drive.google.com/file/d/1au5NCZ-w-OhCEoor1gn5M-bCn_4KJ4oY/view?usp=sharing
를 참고한다

대부분의 주변장치는 char 형
메모리를 어떻게든 많이 할당해야하므로 전용 어드레스에 할당
주변장치는 io로 따로 한다
virture box는 모든 디바이스 드라이브를 지원하지 않음
그냥 멀티 부팅으로 써야한다
하지만 우리는 그냥 해도 된다


이곳이 커널 디렉토리

커널 소스 탐색

~/pi_bsp/kernel/linux$ ARCH=arm make tags

 grep kcci * -r      // kcci가 들어있는 곳 모두 찾기
 find . | grep kcci  // kcci라는 이름이 들어간 모든 파일 찾기
 grep kcci * -r | grep .c$ // .c로 끝나는 kcci라는 이름이 들어간 모든 파일 찾기

그런데 이제 tags를 이용해서 찾을 것이다

~/pi_bsp/kernel/linux$ vi ~/.vimrc

set tags+=/home/ubuntu/pi_bsp/kernel/linux/tags 추가한다

디바이스 드라이버 - 문자
- 블록
- 네트워크

drivers/mics/ : 잡다한 장치들

디스크에서 파일을 읽을 때 fopen, fread 이런 것을 쓰면 실시간성이 떨어진다
왜냐하면 중간에 버퍼를 두고 한단계를 더 거치는데,
저수준 입출력 함수(open, close, read, write)는 그 단계 없이 하기 때문에 빠르다

디바이스 파일을 만들어보자
touch, vi, echo 등 파일은 만드는 방법이 다양하지만
디바이스 파잏은 파일 내 정보를 저장하기 위해서 있기 때문에 다르다

dev는 root 권한이고 일반 소유자는 w 권한이 없다
계정을 처음 만들 때 root 계정은 자동으로 만들어져있고 비밀번호는 없다
그 비밀번호를 변경하려한다

~$ sudo passwd root

새 비밀번호는 rootroot로 했다

~# mknod /dev/devfile c 240 1
c 파일로 주번호 부번호가 나온다


잘못 지우면 큰일난다

~# exit
로그아웃 하는 것이다

어플리케이션에서 디바이스 드라이브를 호출하기 위해 사용한다

이제 mknod 이용한 코드를 만들어 보겠다

~/pi_bsp$ mkdir drivers ; cd drivers
~/pi_bsp/drivers$ mkdir p87 ; cd p87

~/pi_bsp/drivers$ vi mknod.c

  1 #include <sys/types.h>
  2 #include <sys/stat.h>
  3 #include <fcntl.h>
  4 #include <unistd.h>
  5 #include <stdio.h>
  6
  7 int main(int argc, char * argv[])
  8 {
  9     int ret;
 10     ret=mknod("/dev/devfile", S_IRWXU | S_IRWXG | S_IFCHR, (240 << 8) | 1);
 11     if(ret<0)
 12     {
 13         perror("mknod()");
 14         return -ret;
 15     }
 16
 17
 18
 19     return 0;
 20 }

메인함수는 리턴을 +로 해라

~/pi_bsp/drivers/p87$ gcc mknod.c -o mymknod

이 상태에서 바로 실행하면

이렇게 된다
왜냐하면 others에게 권한이 없기 때문이다
그래서

~/pi_bsp/drivers/p87$ sudo ./mymknod

이렇게 실행한다

생성되었다

한번 더 실행하면 perror에 의해 이미 있다고 나온다

unsigned로 출력해서 255가 -1이고, -를 붙여서 1이 되었다

permision 권한에서 0022를 뺀 것
umask때문이다

이제 모듈 테스트이다
커널 2.6으로 할 것

hello.c를 작성한다

  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/kernel.h>
  4
  5 static int hello_init(void)
  6 {
  7     printk("Hello, world\n");
  8     return 0;
  9 }
 10
 11 static void hello_exit(void)
 12 {
 13     printk("Goodbye, world\n");
 14 }
 15
 16 module_init(hello_init);
 17 module_exit(hello_exit);
 18
 19 MODULE_LICENSE("Dual BSD/GPL");
 20

Makefile을 가져온다

  1 MOD := hello
  2 obj-m := $(MOD).o
  3
  4 CROSS = ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
  5 #KDIR := /lib/modules/$(shell uname -r)/build
  6 KDIR := /home/ubuntu/pi_bsp/kernel/linux
  7 PWD := $(shell pwd)
  8
  9 default:
 10     $(MAKE) -C $(KDIR) M=$(PWD) modules $(CROSS)
 11     cp $(MOD).ko /srv/nfs
 12 clean:
 13     rm -rf *.ko
 14     rm -rf *.mod.*
 15     rm -rf .*.cmd
 16     rm -rf *.o
 17     rm -rf modules.order
 18     rm -rf Module.symvers
 19     rm -rf $(MOD).mod
 20     rm -rf .tmp_versions

make

pi에서 커널에 적재시킨다

lsmod | wc -l 하면 갯수가 나오는데
84개이고

sudo insmod hello.ko
명령어 실행하면
85개가 된다


dmesg 하면

이렇게 보인다

그리고

sudo rmmod hello
하면


가버렸다

우분투 지저분하면 make clean 명령어로 없앤다

실습
기존의 내용은 p106_hello로 mv하고
cp로 p106_led로 복사한 뒤
hello.c를 led.c로 mv하고
Makefile 맨 처음의 hello를 led로 바꾼다
init에서 불을 8개 켜고 exit에서 불을 다 끄는 코드를 구현해야한다
코드는 다음과 같다

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h>

#define OFF 0
#define ON 1
#define GPIOLEDCNT 8
#define GPIOKEYCNT 8

int gpioLed[GPIOLEDCNT] = {6,7,8,9,10,11,12,13};
int gpioKey[GPIOKEYCNT] = {16,17,18,19,20,21,22,23};

static int gpioLedInit(void);
static void gpioLedSet(long);
static void gpioLedFree(void);
static int gpioKeyInit(void);
static int gpioKeyGet(void);
static void gpioKeyFree(void);

static int hello_init(void)
{
    int ret;
    printk("Hello, world\n");
    ret=gpioLedInit();
    if(ret < 0)
        return ret;
    gpioLedSet(0xff);
    gpioLedFree();
    printk("led all on\n");

    return 0;
}

static void hello_exit(void)
{
    printk("Goodbye, world\n");
    gpioLedSet(0x00);
    printk("led all off\n");
    gpioLedFree();
}


static int gpioLedInit(void)
{
    int i;
    int ret=0;
    char gpioName[10];
    for(i=0;i<GPIOLEDCNT;i++)
    {
        sprintf(gpioName,"led%d",i);
        ret = gpio_request(gpioLed[i],gpioName);
        if(ret < 0) {
            printk("Failed gpio_request() gpio%d error \n",i);
            return ret;
        }

        ret = gpio_direction_output(gpioLed[i],OFF);
        if(ret < 0) {
            printk("Failed gpio_direction_output() gpio%d error \n",i);
            return ret;
        }
    }
    return ret;
}

static void gpioLedSet(long val)
{
    int i;
    for(i=0;i<GPIOLEDCNT;i++)
    {
        gpio_set_value(gpioLed[i],(val>>i) & 0x1);
    }
}
static void gpioLedFree(void)
{
    int i;
    for(i=0;i<GPIOLEDCNT;i++)
    {
        gpio_free(gpioLed[i]);
    }
}
static int gpioKeyInit(void)
{
    int i;
    int ret=0;
    char gpioName[10];
    for(i=0;i<GPIOKEYCNT;i++)
    {
        sprintf(gpioName,"key%d",gpioKey[i]);
        ret = gpio_request(gpioKey[i], gpioName);
        if(ret < 0) {
            printk("Failed Request gpio%d error\n", 6);
            return ret;
        }
    }
    for(i=0;i<GPIOKEYCNT;i++)
    {
        ret = gpio_direction_input(gpioKey[i]);
        if(ret < 0) {
            printk("Failed direction_output gpio%d error\n", 6);
            return ret;
        }
    }
    return ret;
}
static int  gpioKeyGet(void)
{
    int i;
    int ret;
    int keyData=0;
    for(i=0;i<GPIOKEYCNT;i++)
    {
//      ret=gpio_get_value(gpioKey[i]) << i;
//      keyData |= ret;
        ret=gpio_get_value(gpioKey[i]);
        keyData = keyData | ( ret << i );
    }
    return keyData;
}
static void gpioKeyFree(void)
{
    int i;
    for(i=0;i<GPIOKEYCNT;i++)
    {
        gpio_free(gpioKey[i]);
    }
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("Dual BSD/GPL");
ret=gpioLedInit();
if(ret < 0)
    return ret;
gpioLedSet(val);
gpioLedFree();

ret=gpioKeyInit();
if(ret < 0)
    return ret;
ret=gpioKeyGet();
gpioKeyFree();
return ret;

파일을 복사하려고 한다

현재 : .
끝 : $
아니면 해당 번호


여기다가 아까 복사한 내용을 복사할 것이다

함수 이름에 static 붙이면 함수가 종료돼도 남아있다
-> stack에 안잡힌다
함수나 변수 이름은 유일해야한다
그런데 엄청 많은 소스 중에 함수가 사용되는지 안되는지 일일이 파악하기가 힘들다
그래서 이 파일 안에서만 접근 가능한 함수와 변수를 만들면 외부와 충돌이 일어나지 않는다
모듈 프로그램은 그래서 static으로 지정되어있다
그래서 모든 것을 static으로 했다
shift + 5 : {}로 이루어진 처음과 끝을 왔다갔다 하는 명령어

예전꺼는 커널 api 이용한 커널프로그래밍이었다
부트로더에서 스위치 누르면 ox로 출력하는 기능을 이 곳에 넣기
8번 누르면 while문 빠져나오게 하기

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h>

#define OFF 0
#define ON 1
#define GPIOLEDCNT 8
#define GPIOKEYCNT 8
static int gpioLed[GPIOLEDCNT] = {6,7,8,9,10,11,12,13};
static int gpioKey[GPIOKEYCNT] = {16,17,18,19,20,21,22,23};

static int gpioLedInit(void);
static void gpioLedSet(long);
static void gpioLedFree(void);
static int gpioKeyInit(void);
static int gpioKeyGet(void);
static void gpioKeyFree(void);

static int gpioLedInit(void)
{
    int i;
    int ret=0;
    char gpioName[10];
    for(i=0;i<GPIOLEDCNT;i++)
    {
        sprintf(gpioName,"led%d",i);
        ret = gpio_request(gpioLed[i],gpioName);
        if(ret < 0) {
            printk("Failed gpio_request() gpio%d error \n",i);
            return ret;
        }

        ret = gpio_direction_output(gpioLed[i],OFF);
        if(ret < 0) {
            printk("Failed gpio_direction_output() gpio%d error \n",i);
            return ret;
        }
    }
    return ret;
}

static void gpioLedSet(long val)
{
    int i;
    for(i=0;i<GPIOLEDCNT;i++)
    {
        gpio_set_value(gpioLed[i],(val>>i) & 0x1);
    }
}

static void gpioLedFree(void)
{
    int i;
    for(i=0;i<GPIOLEDCNT;i++)
    {
        gpio_free(gpioLed[i]);
    }
}

static int gpioKeyInit(void)
{
    int i;
    int ret=0;
    char gpioName[10];
    for(i=0;i<GPIOKEYCNT;i++)
    {
        sprintf(gpioName,"key%d",gpioKey[i]);
        ret = gpio_request(gpioKey[i], gpioName);
        if(ret < 0) {
            printk("Failed Request gpio%d error\n", 6);
            return ret;
        }
    }
    for(i=0;i<GPIOKEYCNT;i++)
    {
        ret = gpio_direction_input(gpioKey[i]);
        if(ret < 0) {
            printk("Failed direction_output gpio%d error\n", 6);
            return ret;
        }
    }
    return ret;
}

static int  gpioKeyGet(void)
{
    int i;
    int ret;
    int keyData=0;
    for(i=0;i<GPIOKEYCNT;i++)
    {
//      ret=gpio_get_value(gpioKey[i]) << i;
//      keyData |= ret;
        ret=gpio_get_value(gpioKey[i]);
        keyData = keyData | ( ret << i );
    }
    return keyData;
}

static void gpioKeyFree(void)
{
    int i;
    for(i=0;i<GPIOKEYCNT;i++)
    {
        gpio_free(gpioKey[i]);
    }
}

static int hello_init(void)
{
    int val=0, ret, key_data, key_data_old=0;
    printk("Hello, world \n");

    ret=gpioLedInit();
    if(ret < 0)
    {
        return ret;
    }

    ret=gpioKeyInit();
    if(ret < 0){
        return ret;
    }

    do{
        key_data=gpioKeyGet();
        if(key_data != key_data_old)
        {
            key_data_old=key_data;
            if(key_data)
            {
                val=key_data;
                printk("0:1:2:3:4:5:6:7");
                if(key_data==0x01)
                    printk("O:X:X:X:X:X:X:X");
                else if(key_data==0x02)
                    printk("X:O:X:X:X:X:X:X");
                else if(key_data==0x04)
                    printk("X:X:O:X:X:X:X:X");
                else if(key_data==0x08)
                    printk("X:X:X:O:X:X:X:X");
                else if(key_data==0x10)
                    printk("X:X:X:X:O:X:X:X");
                else if(key_data==0x20)
                    printk("X:X:X:X:X:O:X:X");
                else if(key_data==0x40)
                    printk("X:X:X:X:X:X:O:X");
                else if(key_data==0x80)
                {
                    key_data_old=key_data;
                    gpioLedSet(val);
                    printk("X:X:X:X:X:X:X:O");
                    break;
                }
                key_data_old=key_data;
                gpioLedSet(val);
                printk("\n");
            }
        }
    }while(1);

    gpioKeyFree();
    gpioLedFree();

    return 0;
}

static void hello_exit(void)
{
    printk("Goodbye, world \n");
    gpioLedSet(0x00);
    printk("all off \n");
    gpioLedFree();
    gpioKeyFree();
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("Dual BSD/GPL");
profile
Dragon_muscle

0개의 댓글

관련 채용 정보