소비 전력은 와이파이보다 블루투스가 효율이 좋다
$ 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를 실행해야함
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
모두 다 반복하면
이렇게 최적화 된다
라즈베리파이 코드
#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]);
}
}
너무 어려워용ㅜㅜ