240216

Yonggeun Park·2024년 2월 16일
0

소비 전력은 와이파이보다 블루투스가 효율이 좋다

$ dmesg
$ sudo cat /proc/kmsg

위 두개는 로그 메시지를 확인할 수 있는 명령어이다
쉽게 보여주는 커널 메모리의 인터페이스일 뿐 하드디스크 공간은 아니다

프로세스 foreground/background로 실행하는 법
일반적으로 명령어를 치면 foreground로 돈다

$ firefox

배쉬쉘이 파이어폭스라는 자식프로세스를 만들어서 자식 프로세스가 실행된 것
그 상태에서 명령어를 치면 이전의 프로세스가 종료되기 전까지 먹지않는다
파이어폭스를 닫으면 그제서야 명령어가 수행된다

우분투를 서버용으로 하면 자원 낭비를 막기 위해 터미널 환경으로만 진입한다
하나만 실행하면 안되므로 백그라운드로 한다
명령어는

$ firefox &


작업 번호로 나오고 바로 명령어를 통해 다른 프로세스를 만들 수 있다

$ jobs 명령어를 통해 실행중인 것이 보인다

$ tar cvf pi_bsp.tar pi_bsp/ 
명령어를 실행하면 계속 다운받느라 아무것도 못하는데
ctrl+z를 누르면 멈춤이 된다


$ ps -ef 
실행중인 프로세스 목록을 보여주고
$ ps auwx
명령어로 현재 상태도 보여준다
r=run
s=sleep
t=stop

$ fg %8
명령어로 8번에 있는 작업을 백그라운드로 보낸다



실수로 같은 것을 두번 멈췄다면

ctrl+c로 죽인다

만약 foreground로가 아니라 background로 보내고 싶으면

$ bg %9


이렇게 보낸다
그리고 다시 foreground로 가져올 수도 있다

comport는 1개밖에 안열리므로 foreground/background를 적절히 사용하면 여러 프로그램을 실행할 수 있다.


/var 는 이메일, http, 서버, 로그 등이 있다
로그는 kernel daemon log, sys daemon log로 이루어진다

/var/log$ apt-cache search klog

패키지 목록 중에서 klog가 들어간 것을 보여준다

/var/log$ sudo apt install rsyslog -y
/var/log$ tail -f kern.log  // 또는 sudo cat /proc/kmsg



계속 보여준다
f 대신 숫자를 쓰면 해당 숫자 줄 만큼 나온다
너무 많아서 보기 어려울 때 사용하기 좋을 듯

locate : 어제 업뎃 이후 만든 파일은 db에 없다
sudo update db를 실행해야함

시스템 콜 함수로 LED 제어 구현

STM32 제어할 때 HAL API 사용했던 것처럼 커널에서 사용 한다
1. int gpio_request : gpio 사용 전 요청하는 것
2. void gpio_free : 사용한 gpio를 반환 하는 것
3. int gpio_direction_input : 사용하고자 하는 gpio 번호를 준다
4. int gpio_direction_output : 초기값을 주면서 0을 넘겨준다(1:high)
5. void gpio_set_value : 0, 1을 쓸 수 있다(키면1 끄면0)
6. int gpio_get_value : key의 level을 읽어옴
7. int gpio_to_irq : 외부 인터럽트 기능 활성화 gpio를 irq로 매핑
8. void free_irq : 인터럽트 다 쓰면 반환

우선 1번 led 하나만 켜보겠다
그 전에 ~/pi_bsp/kernel/linux/kernel의 test_mysyscall.c를 수정할 것이다
system call 함수는 리턴이 0보다 작으면 fail이다

#include <linux/kernel.h>
#include <linux/gpio.h>
#define OFF 0
#define ON 1
asmlinkage long sys_mysyscall(long val)
{
//    printk(KERN_INFO "Welcome to KCCI's Embedded System!! app value=%ld\n", val);
    int ret = 0;
    ret = gpio_request(6, "led0");
    if(ret<0)
    {
        printk("Failed gpio_request() gpio%d error\n", 6);
        return ret;
     }
    ret = gpio_direction_output(6,OFF);
    if(ret<0)
    {
        printk("Failed gpio_direction_output() gpio%d error\n", 6);
        return ret;
    }
    gpio_set_value(6, val);
    return 0;
}

적용하기 위해서 빌드 후 zImage를 파이로 옮기고
sync 후 파이를 재부팅한다!

./syscall_app 실행하고 1을 입력하면 1번 LED가 켜지면서

이렇게 된다. 그런데, 다시 0을 입력하게 되면

아까 한거를 free 안해서 fail이 된 것이다!!!!!!
그래서 우분투의 test_mysyscall.c의 아래에

다음과 같이 수정해준다~
그리고 위의 내용을 반복하면

정상적으로 불이 켜지고 꺼지며 출력도 잘 되는 것이다

vi에서 indentation 정리하는 법
정리할 처음 문단의 바로 위에서 v 누르고 맨 마지막 문단의 아래까지 스크롤 한 뒤 = 입력하면 된다

이렇게 코드를 구성했는데, 아래 부분의 usleep(500000); 이랑 sleep(0.5);랑 동일하다!

리눅스는 다중 사용자 환경이다
여러명이 하나의 파일을 수정할 수 있음
그래서 permision이 존재
ls -l 해보면
소유자 그룹 other 순서로 사용 권한이 나온다
한 사람이 파일을 수정할 때 .swp 파일이 생기고 실시간으로 저장되는 상태이다
파일 자체는 안변하고 .swp 파일의 크기만 늘어나는 상황
근데 저장을 하면 그 때 적용이 된다
이 기능을 통해서 비정상적인 세션 종료에도 내용을 복구할 수 있다

$ w 명령어로 누가 접속중인지 확인 가능하다
$ last 로 로그도 나온다

이제 LED 8개를 ON/OFF 해보자 ^ㅡ^;;
test_mysyscall.c를 수정한다

임베디드에서는 메모리를 최대한 아껴야한다
플래시메모리는 그나마 크기 때문에 배열로 선언할 것들, 문자열, 상수을 넣어라


이렇게 수정을했다

그리고 라즈베리로 옮긴뒤 라즈베리파이 코드도 수정해준다

그렇게 하고 gcc 한 뒤 실행해서 85를 입력하면 교차로 출력된다

다시 수정했는데 여러 기능을 추가했다(argument, 입력방식수정 등)


재활용 및 코드 사이즈를 위해 최적화를 한다
:%s/gpioLedCnt/GPIOLEDCNT/g
--> gpioLedCnt로 된 이름을 GPIOLEDCNT로 모두(global) 바꾸겠다

15라인을 잘라서 복사간다
15dd -> p

모두 다 반복하면

이렇게 최적화 된다

실습 : key 제어

라즈베리파이 코드

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <asm-generic/unistd.h>
#pragma GCC diagnostic ignored "-Wunused-result"
int main(int argc, char *argv[])
{
	unsigned int val=0, key_data,key_data_old=0;
	int i;
	if(argc < 2)
	{
		printf("USAGE : %s ledVal[0x00~0xff]\n",argv[0]);
		return 1;
	}
//	printf("input value = ");
//	scanf("%x",&val);
	val = strtoul(argv[1],NULL,16);
    	if(val<0 || 0xff<val)
    	{
    		printf("Usage : %s ledValue(0x00~0xff)\n",argv[0]);
       		return 2;
    	}
	do {
		usleep(100000);  //100MSec
		key_data = syscall(__NR_mysyscall,val);
		if(key_data != key_data_old)
		{
			key_data_old = key_data;
			if(key_data)
			{
				val = key_data;
				puts("0:1:2:3:4:5:6:7");
				for(i=0;i<8;i++)
				{
					if(key_data & (0x01 << i))
						putchar('O');
					else
						putchar('X');
					if(i != 7 )
						putchar(':');
					else
						putchar('\n');
				}
				putchar('\n');
			}
			if(key_data == 0x80)
				break;
		}
	}while(1);
    	printf("mysyscall return value = %#04x\n",key_data);
    	return 0;
}

우분투 코드

#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};

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

asmlinkage long sys_mysyscall(long val)
{
//	printk(KERN_INFO "Welcome to KCCI's Embedded System!! app value=%ld\n",val);
	int ret;
	ret=gpioLedInit();
	if(ret < 0)
		return ret;
	gpioLedSet(val);
	gpioLedFree();

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

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;
}

void gpioLedSet(long val)
{
	int i;
	for(i=0;i<GPIOLEDCNT;i++)
	{
		gpio_set_value(gpioLed[i],(val>>i) & 0x1);
	}
}
void gpioLedFree(void)
{
	int i;
	for(i=0;i<GPIOLEDCNT;i++)
	{
		gpio_free(gpioLed[i]);
	}
}
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;
}
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;
	}
	return keyData;
}
void gpioKeyFree(void)
{
	int i;
	for(i=0;i<GPIOKEYCNT;i++)
	{
		gpio_free(gpioKey[i]);
	}
}
profile
Dragon_muscle

2개의 댓글

comment-user-thumbnail
2024년 2월 16일

너무 어려워용ㅜㅜ

1개의 답글

관련 채용 정보