2009년 12월 21일 월요일

QT4 with OpenCV, How to convert QImage to IplImage

// QImage* qImage, IplImage* cvImage

cvImage = cvCreateImageHeader(cvSize(qImage->width(), qImage->height()), IPL_DEPTH_8U, 4);
cvImage->imageData = (char*)qImage->bits();

2009년 12월 20일 일요일

공대생의 책상..



도대체 정리는 어떻게 해야지 깔끔한 걸까....

큰 맘 먹고 ...



큰 맘 먹고 구입한 Logitech G9x와 G500..

비싸긴 비싸더군;

EZ-X5 Kernel 2.6 Touchpannel Setting (진행중)

---=====  작업 환경 =====---

작업 OS : Fedora 8
EZ-X5 : Kernel 2.6
C/C : arm-linux-3.3.4
Source : kernel 2.6 MK712 source(platform device 기반)
Applications : QT  4.5.2, Tslib  1.0


①  linux-2.6.21\arch\arm\mach-pxa\falinux_ez-x5.c에  아래와 같이 mk712 리소스 부분을 등록.

// mk712 touch [AlProgS] -----------------------------------------------
static struct resource mk712_resources[] = {
        [0] = {
        .name = "mk712_int",
        .start = IRQ_GPIO(22),
        .end = IRQ_GPIO(22),
        .flags = IORESOURCE_IRQ,
        },
};

static struct platform_device mk712_device = {
        .name = "mk712_touchscreen",
        .id = -1,
        .num_resources = ARRAY_SIZE(mk712_resources),
        .resource = mk712_resources,
};
//-----------------------------------------------------------------------


② platform_device 구조체 안에 &mk712_device;  추가.


③ map_desc 구조체 안에 아래와 같이 추가.

{ // nCS1 MK712        -- fast RD/WR
        .virtual  =  0xf1300000,
        .pfn    = __phys_to_pfn(PXA_CS1_PHYS+0x400000),
        .length   =  0x00100000,
        .type   = MT_DEVICE
},


④ 커널 2.4의 mk712.c를 커널 2.6의 커널에 올리기 위해 모듈 컴파일 도중,  컴파일 에러 잡기위해 아래와 같이 수정.

    #include <asm/irq.h>   ->   #include <linux/irq.h>
    #include <asm/io.h>    ->   #include <linux/io.h>

 

⑤ io = 0xf1300000, irq = IRQ_GPIO(22), gpio_irp = 22 로 수정.


⑥ mk712_init 펑션에 다음과 같이 수정.
   -> set_irq_type (MK712_DEFAULT_IRQ, IRQT_RISING);

EZ-X5 LCD Resolution Setting..

  • 수정 소스

-> linux.2.6.21.kernel/arch/arm/mach-pxa/falinux_ez-x5.c
-> linux.2.6.21.kernel/drivers/video/pxafb.c

EZ-X5 작업 환경 셋팅.


호스트호스트 IP 주소
 공유기 192.168.10.1
 PC 192.168.10.2
 EZ-X5 192.168.10.3
 Vmware에 설치된 Linux 192.168.10.10

-= EZBOOT V2.3.15 =-







1) mac address : 00:FA:01:A2:33:15
2) local ip : 192.168.10.3
3) local netmask : 255.255.255.0
4) local gateway : 192.168.10.1
5) server ip : 192.168.10.2
6) zImage file name : zImage
7) ram disk file name : ramdisk-1.10-16M-arm.gz
8) boot loader file name : ezboot.ez-x5
9) logo image file name :
10) auto execute full name :
11) autoboot wait time : 3
12) copy ramdisk [Y/N] : Y
13) arm kernel arch number : 2007
14) nand part (B,C,L,K,R,A): 0,1,0,3,5,119
15) watchdog (sec, off=0) : 0
16) KCMD 1 : mem=128M
17) KCMD 2 : rd_start=0x80800000 rd_size=5M root=/dev/ram0 ramdisk=16384
18) KCMD 3 : console=ttyS0,115200
19) KCMD 4 : video=ezfb:panel:2
20) KCMD 5 :
21) KCMD 6 :

L) Load default
LF) load KCMD2 root=flash
LR) load KCMD2 root=ramdisk
S) Save to flash
P) aPply & exit
Q) Quit

JTAG Cable Pin map (EZ-X5)

 -=  JTAG Cable Pin map =-


JTAG Cable
 1
 2
 3
 4
 5
Serial Cable
 2
 3
 4
13
20


N.T.C 사의 AM-CS2P (Stepping motor driver)

▶ AM-CS2P (스테핑 모터 구동 모듈) 구성


▶ AM-CS2P (스테핑 모터 구동 모듈) 소개

 

▶ AM-CS2P (스테핑 모터 구동 모듈) 제어 신호
 

N.T.C 사의 AB-M128-B (MCU : ATMega128)

▶ AB-M128-B 개발 보드의 구성


AB-M128-B 개발 보드 특징



포트 커넥터 (PORTA ~ PORTF 까지 출력)
 


AB-M128-B 사진

ATMega128 Serial Registers

UDRn - USARTn I/O Data Register

 

UCSRnA - USART Control and Status Register A

 

     RXCn - USART Recive Complete 수신 버퍼에 읽지 않은 데이터가 있을때 1로 설정

                 수신 버퍼가 비어 있다면 클리어

     UDREn - USART Data Register Empty 송신버퍼가 새로운 데이터를 받을 준비가

                 되어 있는지 알려준다.

 

UCSRnB - USART control and status Register B

   

     RXCIEn - RX Complete Interrupt Enable , RXC 플래그를 참조하여 인터펍트를 발생

     RXENn - Receiver Enable , USART 수신을 활성화 시킨다. 수신 버퍼와 관련 동작 가능하도록 한다.

     TXENn - Transmitter Enable , USART 송신을 활성화 시킨다.

     UCSZn2 - Character Size ...............

 

 UCSRnC - USART control and status Register C

 

     UMSELn - USART Mode Select , 동기 or 비동기...설정

     UPMn1:0 - Parity Mode , 패리티 모드의 종류와 설정할 값..

                   00 disabled      01 Reserved

                   10 endabled, Even Parity

                   11 enabled, Odd Parity

     USBSn - USART Stop bit Select , Stop 비트 설정

     UCSZn1:0 - UCSRB의 UCSZ2와 관련하여 Character Size 와 관련된 비트..

                  UCSZ2 UCSZ1 UCSZ0.............

                  000  5bit             001 , 010, 011      6,7,8bit

                  100, 101, 110  reserved          111  9bit

   

 UBRRnL - USART Baud Rate Registers

 UBRRnH - USART Baud Rate Registers

ATMega128 Serial Communications

● ATMega128 통신 포트

  - UART0 (RXD0, TXD0)
  - UART1 (RXD1, TXD1)


  -> UART0,1은 5v 레벨 신호.
  -> MAX232로 10v 레벨 신호로 변환.
  -> ATMega128 <-> PC 간 rs232 통신 확인 완료.
 

● ATMega128의 UART0 Pin map
 

 1
  2 
 3
 4
 Vcc(12V)
    TxD    
    RxD   
   GND   
 

● ATMega128 <-> PC 간 통신 회로도


● RS232 cable pin map

ATMega128 Datasheet & Circuit Diagram

MCU : ATmega 128
 ->   datasheet.pdf
ROM : AT29C256
 ->   datasheet.pdf

QT4 with OpenCV, How to convert IplImage to QImage

void Canvas::setImage(const IplImage *newImage)
{
    uchar *qImageBuffer = NULL;

    int width = newImage->width;
    int widthStep = newImage->widthStep;
    int height = newImage->height;
    if(width!=old_w||height!=old_h||widthStep!=old_ws) {
        imageq = QImage();
    }
    qImageBuffer = (uchar *) malloc(width*height*4*sizeof(uchar));
    uchar *QImagePtr = qImageBuffer;
    int  linestep;
    const uchar *iplImagePtr = (const uchar *) newImage->imageData;
    if (newImage->origin==0) {
        linestep = widthStep-3*width;
    } else { // If image got origin from bottom-left
        linestep = (widthStep+(3*width))*-1;
        iplImagePtr += widthStep * (height-1);
    }
    for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                // We cannot help but copy manually.
                QImagePtr[0] = iplImagePtr[0]; // B
                QImagePtr[1] = iplImagePtr[1]; // G
                QImagePtr[2] = iplImagePtr[2]; // R
                QImagePtr[3] = 0xff; // Alpha
                QImagePtr += 4;
                iplImagePtr += 3;
            }
            iplImagePtr += linestep;
        }
    QImage *tempimg;
    tempimg = new QImage(qImageBuffer, width, height,QImage::Format_RGB32);
    imageq = tempimg->copy(0,0,width,height);
    free(qImageBuffer);
}

형 변환

QString 을 C type 형으로 변환
1. char
2. char[]
3. int
4. long

QString aaa;

1. aaa.ascii()[0];
2. aaa.ascii()(;
3. aaa.toInt();
3. aaa.toLong();

int 형을 QString으로 변경 시키는 방법
QString a;
int b = 10;

a = a.setNum(b);

char형을 QString으로 변경 시키는 방법
char szFullPath[100];
strcpy(szFullPath, "world");
QString data;
QString how;
   
data = "Hello ";
how = data + QString(szFullPath);

Tslib 1.0

 

▶ Tslib 1.0


Step1. 설정
 
 ./configure --prefix=/qt3/tslib --enable-inputapi --enable-shared --disable-h3600 --disable-corgi --disable-collie --enable-input --enable-mk712 --disable-arctic2 --disable-ucb1x00 --build=i386-linux --host=arm-linux CC=arm-linux-gcc


Step2. 소스 수정
 

 

 - config.h 수정

 

 [ #define malloc rpl_malloc ] 라인 주석 처리



Step3. make & make install

 # make

 # make install



Step4. 환경변수 설정

 

export TSDIR=/qt4/tslib-arm

export LD_LIBRARY_PATH=$TSDIR/lib:$LD_LIBRARY_PATH

export TSLIB_TSDEVICE=/dev/mk712

export TSLIB_CONFFILE=/qt4/tslib-arm/etc/ts.conf

export TSLIB_CALIBFILE=/etc/pointercal

export TSLIB_FBDEVICE/dev/fb0

export QWS_MOUSE_PROTO=tslib:$TSLIB_TSDEVICE

export QWS_SIZE=1024x768

 

QT configure options (EZ-X5)

-> qt/e(3.3.3)


./configure -embedded arm -shared -thread -debug -no-cups -continue -qt-mouse-linuxtp -qt-zlib -qt-gif -qt-libpng -no-libmng -qt-libjpeg

QT FTP site

-> ftp://ftp.trolltech.com/qt/source/ 

ZigBee, ATmega128 과 PC 연결 방법.

● Pin connections




  -> ATMega128 - UART0  - TxD  -- >  XBee Pin3
                                      - RxD  -- >  XBee Pin2

  -> PC             - RS232   - TxD  -- >  MAX232 Pin13
                                      - RxD  -- >  MAX232 Pin14
                                                        MAX232 Pin11 -- > XBee Pin2
                                                        MAX232 Pin12 -- > XBee Pin3

DiGi Mesh Xbee Moudle 칩 안테나 타입(XB24-DMCIT-250J)

● XBee Photo



● XBee Datasheet



  -> Data-sheet-max-stream.pdf



● XBee Pin map





● Minimum connections


  -> Vcc, GND, DIN, DOUT.

VI Commands

vi Editor's Command Collection

 command line 명령어

내 용

vi file

vi를 시작하여 지정한 파일 편집

vi -r file

읽기 전용(read- only) 편집기로서 vi를 시작하여 지정한 파일 편집

view file

읽기 전용(read- only) 편집기로서 vi를 시작하여 지정한 파일 편집

vi -r

되살릴 수 있는 모든 파일 이름 보여주기

vi -r file

vi를 시작하여 지정한 파일 되살리기



편 집 명 령

내 용

i

입력 모드로 전환, 커서 위치 앞에서 삽입

a

입력 모드로 전환, 커서 위치 뒤에서 삽입

I

입력 모드로 전환, 현재 줄의 앞에 삽입

A

입력 모드로 전환, 현재 줄의 끝에 삽입

o

입력 모드로 전환, 현재 줄의 아래에 전개

O

입력 모드로 전환, 현재 줄의 위에 전개

:e file

지정한 파일의 편집

:e! file

지정한 파일의 편집, 자동 점검의 생략

r

단지 한 글자만 변경(입력 모드로 바뀌지 않음)

R

입력하는 대로 겹쳐 써서 변경

s

삽입에 의해 한 단어의 변경

C

커서의 위치로부터 줄 끝까지 삽입에 의한 변경

cc

전체 줄을 삽입에 의한 변경

S

전체 줄을 삽입에 의한 변경

cmove

커서부터 move까지 삽입에 의해 변경

~

대,소문자 바꾸기

u

편집 버퍼를 수정했던 마지막 명령을 취소

U

현재 줄을 저장

.

편집 버퍼를 수정했던 마지막 명령 반복

x

커서가 있는 문자 삭제

X

커서의 왼쪽 문자 삭제

D

커서부터 줄의 끝까지 삭제

dd

현재 줄의 전체 삭제

dmove

커서부터 move까지 삭제

dG

커서부터 편집 버퍼의 끝까지 삭제

d1G

커서부터 편집 버퍼의 맨 앞까지 삭제

:<line>d

지정한 줄의 삭제

:<line>,<line>d

지정한 범위의 삭제

:<line>co<target>

지정한 줄을 복사하여 target 줄 밑에 삽입

:<line>, <line>co<target>

지정한 범위를 복사하여 target 줄 밑에 삽입

:<line>m<target?

지정한 줄로 이동하여 target 줄 밑에 삽입

:<line>, <line>m<target>

지정한 범위로 이동하여target 줄 밑에 삽입

<n>!!command

n번 줄에서 command의 실행

!move command

커서부터 move까지 command 실행

!move fmt

커서부터 move까지 줄들을 형식 맞추기

:w

원래의 파일로 데이터를 저장

:w file

지정한 파일로 데이터를 저장

:w>> file

지정한 파일에 데이터를 추가

:wq

데이터를 저장하고 종료

:q!

데이터를 저장하지 않고 종료

:set number

내부 줄 번호 디스플레이

:set nonumber

내부 줄 번호 디스플레이 않기

p

마지막으로 지워진 것을 커서의 뒤/아래에 삽입

P

마지막으로 지워진 것을 커서의 앞/위에 삽입

xp

두 문자를 바꿈

deep

두 단어를 바꿈

ddp

두 줄을 바꿈

/rexp

지정된 정규 표현식에 대해 앞으로 이동

/

이전의 패턴에 대해 앞으로 검색을 반복

?rexp

지정된 정규 표현식에 대해 뒤로 이동

?

이전의 패턴에 대해 뒤로 검색을 반복

n

/나 ?명령에 대해 같은 방향으로 반복

N

/나 ?명령에 대해 반대 방향으로 반복

:ab short long

short를 long에 대한 약어로 변경

:ab

현재 약어 목록을 표시

:una short

약어 short를 표시

r<Return>

문자를 뉴라인으로 변경

J

아래 line을 현재 line과 합치기

:set wm=n

오른쪽으로 n문자 위치에서 자동적으로 줄 나눔

h or <Left key>

커서를 한 칸 왼쪽으로 이동

j or <Down key>

커서를 한 줄 아래로 이동

k or <Up key>

커서를 한 줄 위로 이동

l or <Right key>

커서를 한 칸 오른쪽으로 이동

<Backspace>

커서를 한 칸 왼쪽으로 이동

<Space>

커서를 한 칸 오른쪽으로 이동

-

커서를 이전 줄의 처음으로 이동

+

커서를 다음 줄의 처음으로 이동

<Return>

커서를 다음 줄의 처음으로 이동

0

커서를 현재 줄의 맨 앞으로 이동

$

커서를 현재 줄의 맨 끝으로 이동

^

커서를 현재 줄의 첫글자(공백이나 탭이 아닌)로 이동

w

커서를 다음 단어의 첫 글자로 이동

e

커서를 다음 단어의 끝 글자로 이동

b

커서를 이전 단어의 첫 글자로 이동

W

w와 같음(문장 부호 무시)

E

e와 같음(문장 부호 무시)

B

b와 같음(문장 부호 무시)

(

다음 문장의 처음으로 이동

)

이전 문장의 처음으로 이동

{

다음 문단의 처음으로 이동

}

이전 문단의 처음으로 이동

H

커서를 화면 맨 위로 이동

M

커서를 중간으로 이동

L

커서를 맨 아래로 이동

^f

한 화면 아래로 이동

^b

화면 위로 이동

^d

반 화면 아래로 이동

^u

반 화면 위로 이동

n^d

n줄만큼 아래로 이동

n^u

n줄만큼 위로 이동

:!command

vi를 중단하고 지정한 셸 명령을 실행

:!!

vi를 중단하고 이전의 셸 명령을 실행

:sh

vi를 중단하고 셸을 실행

:!csh

vi를 중단하고 새로운 C-셸을 실행

:s/<pattern>/<replace>/

현재 줄의 치환

:<line>s/<pattern>/<replace>/

지정한 줄의 치환

:<line>,<line>s/<pattern>/<replace>/

정한 범위의 치환

:%s/<pattern>/<replace>/

모든 줄의 치환

:<line>r file

file의 내용을 지정한 줄 다음에 삽입

:r file

file의 내용을 현재의 줄 다음에 삽입

:<line>r !command

command의 결과를 지정한 줄 다음에 삽입

:r !command

command의 결과를 현재의 줄 다음에 삽입

:r !look pattern

지정한 pattern으로 시작된 단어 삽입

.

뉴라인을 제외한 모든 단일 문자와 대응

*

영 또는 그 이상의 선행 문자와 대응

^

줄의 시작과 대응

$

줄의 끝과 대응

\<

단어의 시작과 대응

\>

단어의 끝과 대응

[ ]

묶여진 문자중의 하나와 대응

[^ ]

묶여진 문자를 제외한 아무것하고나 대응

\

이어지는 기호를 문자 그대로 해석

<n>G

줄번호 n으로 건너뛰기

1G

편집 버퍼의 첫 줄로 건너뛰기

G

편집 버퍼의 마지막 줄로 건너뛰기

:map g lG

g가 lG와 같도록 매크로 정의


< 표 출처 : http://if.kaist.ac.kr/~jskim/Home/etc/vi.html >

Linux Kernel API

2장
insmod
modprobe
rmmod
실행 커널로 모듈을 적재하고 제거하는 사용자 영역 유틸리티

#include <linux/init.h>
module_init(init_function);
module_exit(cleanup_function);
모듈 초기화 함수와 정리 함수를 지정하는 매크로

#include <linux/sched.h>
sleeping관련 함수 변수, 드라이버의 Kernel API대부분의 정의
stuct task_struct *current;
현재 프로세스
current->pid
current->comm
현재 프로세스 ID와 명령 이름
obj-m
커널 빌드 시스템이 현재 디렉토리에서 빌드할 모듈을 파악하는데 사용하는 makefile심벌
/sys/module
적재된 모듈 정보를 포함하는 sys 디렉토리 층
/proc/modules
모듈 정보표시 가상 파일

#include <linux/module.h>
#include <linux/version.h>

LINUX_VERSION_CODE
버전 의존성 확인 정수 매크로 #ifdef로 사용

EXPORT_SYMBOL (symbol);
EXPORT_SYMBOL_GPL (symbol);
심벌을 외부에 공개

MODULE_AUTHOR(author);
MODULE_DESCRIPTION(description);
MODULE_LICENSE(license_string);
MODULE_VERSION(version_string);
MODULE_DEVICE_TABLE(table_info);
MODULE_ALIAS(alternate_name);
모듈 정보를 목적파일에 삽입

#include <linux/moduleparam.h>
module_param(variable, type, perm); // S_IRUGO
module_param_array(name, type, num, perm); // S_IRUGO
사용자가 지정할 수 있는 매개변수 만드는 매크로
bool, charp, int, invbool, long, short, ushort, uint, unlong, intarray

#include <linux/kernel.h>
int printk(const char* fmt, ...);


3장
#include <linux/types.h>
dev_t
디바이스 번호 타입

int MAJOR(dev_t dev);
int MINOR(dev_t dev);
디바이스 번호에서 주, 부번호를 얻어냄

dev_t MKDEV(unsigned int major, unsigned int minor);
주, 부번호에서 dev_t 자료 아이템 생성

#include <linux/fs.h>
파일시스템 함수
int register_chrdev_region(dev_t first, unsigned int count, char *name)
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name)
int unregister_chrdev_region(dev_t first, unsigned int count);
디바이스 번호를 할당/해제 reg:번호를 알때, alloc:동적 할당

int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);
major가 0이면 동적, 0이 아니면 그 번호 사용 커널 2.6버전 이전
int unregister_chrdev(unsigned int major, const char *name);
해제

struct file_operations;
문자 드라이버 메소드
struct file;
열린 파일 표현
struct inode;
디스크 상의 파일

#include <linux/cdev.h>
struct cdev *cdev_alloc(void);
void cdev_init(struct cdev *dev, struct file_operations *fops);
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
void cdev_del(struct cdev *dev);
문자 디바이스 구조체 관리

#include <linux/kernel.h>
container_of(pointer, type, field);
다른 구조체에 포함된 구조체 포인터 받아 해당 구조체를 포함하는 구조체 포인터를 반환

#include <asm/uaccess.h>
커널 코드가 사용자 영역으로 자료 전송
unsigned long copy_from_user(void *to, const void *from, unsigned long count);
unsigned long copy_to_user(void *to, const void *from, unsigned long count);
사용자 영역과 커널 영역간 자료 복사

 

5장
#include <asm/semaphore.h>
DECLARE_MUTEX(name);
DECLARE_MUTEX_LOCKED(name);
세마포어 정의, 초기화 매크로

void init_MUTEX(struct semaphore *sem);
void init_MUTEX_LOCKED(struct semaphore *sem);
실행 시점에서 세마포어 초기화

void down(struct semaphore *sem); // 호출 프로세스를 인터럽트 불가상태로 잠재움
int down_interruptible(struct semaphore *sem); // 시그널로 인터럽트 가능
int down_trylock(struct semaphore *sem); // 세마포어 불가시 함수 반환
void up(struct semaphore *sem); // 락을 해제
세마포어에 락을 걸고, 해제

struct rw_semaphore;
init_rwsem(struct rw_semaphore *sem);
읽기/쓰기 스레드 세마포어

void down_read(struct rw_semaphore *sem);
int down_read_trylock(struct rw_semaphore *sem);
void up_read(struct rw_semaphore *sem);
void down_write(struct rw_semaphore *sem);
"
"
void downgrade_write(struct rw_semaphore *sem);

#include <linux/completion.h>
DECLARE_COMPLETION(name);
init_completion(struct completion *c); // 처음 초기화
INIT_COMPLETION(struct completion c); // 재초기화

void wait_for_completion(struct completion *c);
완료 시그널을 기다림
void complete(struct completion *c); // 스레드중 하나 깨움
void complete_all(struct completion *c); // 모든 대기자 깨움
완료 시그널 보냄
void complete_and_exit(struct completion *c, long retval);
완료 후 현 스레드에서 exit호출

#include <linux/spinlock.h>
spinlock_t lock = SPIN_LOCK_UNLOCKED;
spin_lock_init(spinlock_t *lock);
스핀락 초기화 두 방법

void spin_lock(spinlock_t *lock); //_irqrestore, _irq, _bh
void spin_trylock(spinlock_t *lock); // 스핀하지 않음
void spin_unlock(spinlock_t *lock); // 스핀락 해제


rwlock_t lock = RW_LOCK_UNLOCKED
rwlock_init(rwlock_t *lock);
읽기/쓰기 스레드 락 초기화 시키는 두 방법
void read_lock(rwlock_t *lock); //_irqrestore, _irq, _bh
void read_unlock(rwlock_t *lock);
void write_lock(rwlock_t *lock);
void write_unlock(rwlock_t *lock);


#include <asm/atomic.h>
atomic_t v = ATOMIC_INIT(value);
int atomic_read(atomic_t *v);
void atomic_set(atomic_t *v, int i);
void atomic_add(int i, atomic_t *v);
void atomic_sub(int I, atomic_t *v);
void atomic_inc(atomic_t *v);
void atomic_dec(atomic_t *v);
int atomic_sub_and_test(int I, atomic_t *v);
int atomic_add_negative(int I, atomic_t *v);
int atomic_dec_and_test(atomic_t *v);
int atomic_inc_and_test(atomic_t *v);
int atomic_inc_return(atomic_t *v);
원자 정수 변수. atomic_t 변수는 위의 함수로만 접근 가능

#include <asm/bitops.h>
void set_bit(int nr, void *addr);
void clear_bit(int nr, void *addr);
void change_bit(int nr, void *addr);
void test_and_set_bit(int nr, void *addr);
void test_and_clear_bit(int nr, void *addr);
void __set_bit(int nr, void *addr)
void __clear_bit(int nr, void *addr)
void __change_bit(int nr, void *addr)
원자 비트 변수. 플래그나 락 변수로 활용.

#include <linux/seqlock.h>
seqlock_t lock = SEQLOCK_UNLOCKED;
seqlock_init(seqlock_t *lock);
unsigned int read_seqbegin_irqsave(seqlock_t *lock, unsigned long flags); // 읽기 권한 얻기
int read_seqretry_irqrestore(seqlock_t *lock, unsigned int seq, unsigned long flags); // 읽기 권한 얻기
void write_seqlock_irqsave(seqlock_t *lock, unsigned long flags); // 쓰기 권한 얻기
void write_seqlock_irq(seqlock_t *lock); // 쓰기 권한 얻기
void write_seqlock_bh(seqlock_t *lock);
void write_sequnlock_irqrestore(seqlock_t *lock, unsigned long flags); // 쓰기 권한 해제
void write_sequnlock_irq(seqlock_t *lock);
void write_sequnlock_bh(seqlock_t *lock);


#include <linux/rcupdate.h>
Read - Copy - Update 매커니즘을 사용하기 위한 해더
void rcu_read_lock();
void rcu_read_unlock();
Atomic 읽기 접근

void call_rcu(struct rcu_head *head, void (*func)(void *arg), *void arg);
모든 프로세서가 스케줄 되어 RCU 해제해도 안전할 때 수행할 콜백 등록 함수


6장
#include <linux/ioctl.h>

#include <asm/uaccess.h>
int access_ok(int type, const void *addr, unsigned long size);
사용자 영역 포인터를 실제로 사용할 수 있는지 확인한다. 포인터를 참조해도 된다면 access_ok는 0이 아닌값 반환
type : VERIFY_READ, VERIFY_WRITE

int put_user(datum, ptr); // access_ok를 이미 호출
int __get_user(local, ptr); // __는 access_ok를 이미 호출했다고 가정
자료를 사용자 영역에서 가져오거나 저장 매크로, 전송 용량은 sizeof(*ptr)

#include <linux/capability.h>
사용자 영역 프로세스의 능력을 지정
int capable(int capability);
프로세스에 주어진 capbility가 있으면 0이 아닌값 반환

#include <linux/wait.h>
typedef struct { /*...*/ } wait_queue_head_t; // 명시적 초기화 필요
void init_waitqueue_head(wait_queue_head_t *queue); // 실행 시점에서 초기화
DECLARE_WAIT_QUEUE_HEAD(queue); // 컴파일 시점에서 초기화
리눅스 대기 큐에 대한 타입 정의

void wait_event(wait_queue_head_t q, int condition);
void wait_event_interruptible(wait_queue_head_t q, int condition);
void wait_event_timeout(wait_queue_head_t q, int condition, int time);
void wait_event_interruptible_timeout(wait_queue_head_t q, int condition, int time);
주어진 컨디션이 참이 될 때 까지 큐에서 프로세스가 자게 만든다.

void wake_up(struct wait_queue **q);
void wake_up_interruptible(struct wait_queue **q); // interruptible한 프로세스만 깨움
void wake_up_nr(struct wait_queue **q int nr); //
void wake_up_interruptible_nr(struct wait_queue **q, int nr);
void wake_up_all(struct wait_queue **q);
void wake_up_interruptible_all(struct wait_queue **q);
void wake_up_interruptible_sync(struct wait_queue **q);
큐에서 잠든 프로세스를 깨운다. 일반적으로 상호배제 중인 프로세서 1개만

#include <linux/sched.h>
set_current_state(int state);
현재 프로세스의 실행 상태를 설정
TASK_RUNNING
TASK_INTERRUPTIBLE
TASK_UNINTERRUPTIBLE

void schedule(void);
실행 큐에서 실행 가능 프로세스를 선택

typedef struct { /*...*/ } wait_queue_t; // 명시적 초기화 필요
init_waitqueue_entry(wait_queue_t *entry, struct task_struct *task);
wait_queue_t타입을 사용하여 프로세스를 대기 큐에 넣는다.

void prepare_to_wait(wait_queue_head_t *queue, wait_queue_t *wait, int state);
수작업으로 잠들기 구현

#include <linux/poll.h>
void poll_wait(struct file *filp, wait_queue_head_t *q, poll_table *p)
현재 프로세스를 즉시 스케줄링하지 않고 대기 큐에 넣는다. 디바이스 드라이버의 poll메소드가 사용

int fasync_helper(struct inode *inode, struct file *filp, int mod, struct fasync_struct **fa);
//몰라

 


7장
시간 맞추기
#incldue <linux/param.h>
HZ : 초당 클록 틱 수

#include <linux/jiffies.h>
volatile unsigned long jiffies
u64 jiffies_64 // 매 클럭 틱마다 1씩 증가

int time_after(unsigned long a, unsigned long b);
int time_before(unsigned long a, unsigned long b);
int time_after_eq(unsigned long a, unsigned long b);
int time_before_eq(unsigned long a, unsigned long b);
지피를 안전하게 비교(오버플로우x)
u64 get_jiffies_64(void);
경쟁없이 지피값 가져옴

#include <linux/time.h>
unsigned long timespec_to_jiffies(struct timespec *value);
void jiffies_to_timespec(unsigned long jiffies, struct timespec *value);
unsigned long timeval_to_jiffies(struct timeval *value);
void jiffies_to_timeval(unsigned long jiffies, struct timeval *value);
지피를 다른 시각 표현으로, 시각을 지피로 변환

#include <asm/msr.h>
rdtsc(low32,high32); // 32 32 둘다
rdtscl(low32); // 하위
rdtscll(var64); // 64 longlong 변수
타임스탬프 카운터를 읽는 매크로 x86 32bit*2

#include <linux/timex.h>
cycles_t get_cycles(void);
플랫폼 의존적으로 타임스탬프 카운터 반환, 기능 지원X = 0

#include <linux/time.h>
unsigned long mktime (unsigned int year, unsigned int mon,
   unsigned int day, unsigned int hour,
   unsigned int min, unsigned int sec);
년월일시분초 받아서 기준시부터 얼마나 흘렀는지 반환
void do_gettimeofday(struct timeval *tv);
현재시간을 기준 시각 이후 초와 마이크로초로 반환
struct timespec current_kernel_time(void);
1지피 resolution으로 현재시각을 반환

지연
#include <linux/wait.h>
long wait_event_interruptible_timeout(wait_queue_head_t *q, contion, signed long timeout);
현재 프로세스를 대기큐에 넣고 재움, 타임아웃은 지피값
#include <linux/sched.h>
signed long schedule_timeout(signed long timeout);
타임아웃 만료시 현재 프로세스가 깨어났음을 확인 후 스캐줄러 호출. 인터럽트 불가
호출자는 잠자기전에 set_current_state호출 해야함

#include <linux/delay.h>
void ndelay(unsigned long nsecs);
void udelay(unsigned long usecs);
void mdelay(unsigned long msecs);
각 단위 지연
void msleep(unsigned int millisecs);
unsigned long msleep_interruptible(unsigned int millisecs);
void ssleep(unsigned int seconds)
주어진 밀리초 만큼 프로세스를 재움


커널 타이머
#include <asm/hardirq.h>
int in_interrupt(void); // 프로세스 context 밖
int in_atomic(void); // 스핀락, 인터럽트 스캐줄링 해서 안되는 경우
bool반환 호출 코드가 어떤 context에서 실행중인지 반환

#include <linux/timer.h>
struct timer_list {
 /* ... */
 unsigned long expires;
 void (*function)(unsigned long);
 unsigned long data;
};
void init_timer(struct timer_list *timer);
struct timer_list TIMER_INITIALIZER(_function, _expires, _data);
timer_list 자료 구조체 초기화

void add_timer(struct timer_list * timer);
현재 CPU에서 실행하도록 타이머 구조체 등록
int del_timer(struct timer_list * timer);
int del_timer_sync(struct timer_list *timer); // 다른 CPU에서 실행중 아님을 보장
활성 타이머 목록에서 타이머 제거
int mod_timer(struct timer_list *timer, unsigned long expires);
이미 스케줄된 타이머 구조체의 만료시간 변경, add대신 사용가능
int timer_pending(const struct timer_list * timer);
타이머구조체를 이미 등록했는지 bool반환

태스크릿
#include <linux/interrupt.h>
struct tasklet_struct {
 /* ... */
 void (*func)(unsigned long);
 unsigned long data;
};
void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data);
이미 할당된 태스크릿 초기화
DECLARE_TASKLET(name, func, data);
DECLARE_TASKLET_DISABLED(name, func, data); // 비활성화 상태로 표시
태스크릿 구조체 정의
void tasklet_disable(struct tasklet_struct *t); // 다른 CPU에서 실행중일 경우 끝날때 까지 대기
void tasklet_disable_nosync(struct tasklet_struct *t); // 대기 안하고 반환
void tasklet_enable(struct tasklet_struct *t);
태스크릿을 활성/비활성화
void tasklet_schedule(struct tasklet_struct *t);
void tasklet_hi_schedule(struct tasklet_struct *t);
보통/ 높은 우선순위로 태스크릿 수행토록 스캐줄링
void tasklet_kill(struct tasklet_struct *t);
활성 태스크릿 목록에서 제거 // 다른 CPU에서 실행중일 경우 끝날때 까지 대기

작업큐
#include <linux/workqueue.h>
struct workqueue_struct;
struct work_struct;
작업큐와 작업항목 구조체

struct workqueue_struct *create_workqueue(const char *name); // 프로세서마다 작업자 스레드가 있는 작업큐 생성
struct workqueue_struct *create_singlethread_workqueue(const char *name); // 작업자 스레드가 하나뿐인 작업큐 생성
void destroy_workqueue(struct workqueue_struct *queue);
작업큐 생성/해제
DECLARE_WORK(name, void (*function)(void *), void *data);
INIT_WORK(struct work_struct *work, void (*function)(void *), void *data);
PREPARE_WORK(struct work_struct *work, void (*function)(void *), void *data);
작업큐항목 선언, 초기화
int queue_work(struct workqueue_struct *queue, struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *queue, struct work_struct *work, unsigned long delay);
작업큐에 작업 삽입
int cancel_delayed_work(struct work_struct *work); // 작업 항목 제거
void flush_workqueue(struct workqueue_struct *queue); // 시스템에 실행 중인 작업큐 모두 제거

int schedule_work(struct work_struct *work);
int schedule_delayed_work(struct work_struct *work, unsigned long delay);
void flush_scheduled_work(void);
공유 작업 큐로 작업용


9장
#include <linux/kernel.h>
void barrier(void)
소프트웨어 메모리 장벽은 컴파일러에게 이 명령 전후 모든 메모리를 volatile접근으로 간주하라 요청

#include <asm/system.h>
void rmb(void);
void read_barrier_depends(void);
void wmb(void);
void mb(void);
하드웨어 메모리 장벽은은 CPU와 컴파일러에게 이 명령 전후의 모든 메모리 읽기 쓰기 둘다를 점검하라 요청

#include <asm/io.h>
unsigned inb(unsigned port);
void outb(unsigned char byte, unsigned port);
unsigned inw(unsigned port);
void outw(unsigned short word, unsigned port);
unsigned inl(unsigned port);
void outl(unsigned double word, unsigned port);
I/O port를 읽고 쓰는 함수

~_p I/O연산을 짧은 시간 지연할 필요가 있을 때.

void insb(unsigned port, void *addr, unsigned long count);
void outsb(unsigned port, void *addr, unsigned long count);
void insw(unsigned port, void *addr, unsigned long count);
"
"

문자열 함수, 입력 포트 -> 메모리 영역, 메모리 영역 -> 출력 포트 count 개수 만큼 자료 전송

#include <linux/ioport.h>
struct resource *request_region(unsigned long start, unsigned long len, char *name);
void release_region(unsigned long start, unsigned long len);
int check_region(unsigned long start, unsigned long len);
I/O 포트 자원 할당자.

struct resource *request_mem_region(unsigned long start, unsigned long len, char *name);
void releas_mem_region(unsigned long start, unsigned long len);
int check_mem_region(unsigned long start, unsigned long len);
메모리 영역 자원 할당 처리 함수

#include <asm/io.h>
void *ioremap(unsigned long phys_addr, unsigned long size);
void *ioremap_nocache(unsigned long phys_addr, unsigned long size);
void *iounmap(void *virt_addr);
ioremap은 물리적 주소 영역을 프로세서의 가상 주소 영역에 재사상하여 커널에서 사용할 수 있게 함, 사상 해제

#include <asm/io.h>
unsigned int ioread8(void *addr); // 16, 32
void iowrite8(void *addr); // 16, 32
I/O 메모리 접근 함수

unsigned int ioread8_rep(void *addr); // 16, 32
void iowrite8_rep(void *addr); // 16, 32
I/O 메모리 접근 함수 반복

unsigned readb(address); /b, w, l
unsigned writeb(address); /b, w, l
memset_io(address, value, count);
memset_fromio(dest, source, nbyte);
memset_toio(dest, source, nbyte);
예전 함수

void *ioport_map(unsigned long port, unsigned int count);
void ioport_unmap(void *addr);
I/O 포트를 I/O 메모리처럼 취급하려면 포트를 ioport_map으로 넘긴다.

 

10장
#include <linux/interrupt.h>
int request_irq(unsigned int irq, irqreturn_t (*handler)(), unsigned long flags, const char *dev_name, void *dev_id);
void free_irq(unsigned int irq, void *dev_id);
인터럽트 핸들러를 등록, 해제

#include <linux/irq.h>
int can_request_irq(unsigned int irq, unsigned long flags);
x86에서 사용 인터럽트 선 할당 성공시 0이 아닌 값 반환

#include <asm/signal.h>
SA_INTERRUPT 빠른 핸들러 설치
SA_SHIRQ 공유 핸들러
SA_SAMPLE_RANDOM 시스템 엔트로피 생성에 인터럽트 타임스탬프 사용

/proc/interrupt
/proc/stat
하드웨어 인터럽트와 설치된 핸들러에 대한 정보를 보여주는 파일 시스템의 노드

unsigned long probe_irq_on(void);
int probe_irq_off(unsigned long);
탐색과정에서 디바이스가 사용할 인터럽트 선을 결정할 때 드라이버에서 사용하는 함수.
인터럽트 생성 후 probe_irq_on결과를 probe_irq_off로 넘겨야한다.
probe_irq_off의 반환값은 감지한 인터럽트 번호

IRQ_NONE
IRQ_HANDLED
IRQ_RETVAL(int x)
인터럽트 핸들러가 반환할 수 있는 값

void disable_irq(int irq);
void disable_irq_nosync(int irq);
void enable_irq(int irq);
인터럽트 보고를 활성/비활성화. 공유처리기는 사용 불가

void local_irq_save(unsigned long flags);
void local_irq_restore(unsigned long flags);
현재 프로세서에서 인터럽트 비활성화 이전상태 기억 - 복구

void local_irq_disable(void);
void local_irq_enable(void);
현재 프로세서에서 인터럽트를 무조건 활성화/비활성화

OpenCV, Qt3 와 연동하기

⊙ .pro file에 다음 항목들을 추가.

LIBS += -L/Project/OpenCV/lib ::::: OpenCV library folder
INCLUDEPATH += /Project/OpenCV/include ::::: OpenCV include folder

 ⊙ Makefile 수정.

  -> 아래 항목을 찾아 내용 추가.

 INCPATH = -I/Project/OpenCV/include ::::: OpenCV include folder
 LIBS = -L/Project/OpenCV/lib -lcxcore -lcv -lhighgui -lcvaux -lml ::::: OpenCV library folder

 ⊙ .cpp에 필요한 헤더 선언

 ex) #include "opencv/cv.h"

OpenCV, EZ-X5에 포팅하기

1. Linux 용 OpenCV 1.0 Download

[root@localhost OpenCV]# wget http://downloads.sourceforge.net/opencvlibrary/opencv-1.0.0.tar.gz

[root@localhost OpenCV]# tar xvfz opencv-1.0.0.tar.gz


2. OpenCV 1.0 Crosscompile configure options


[root@localhost opencv-1.0.0]# ./configure CXX=/usr/arm-linux/bin/g++ --host=arm-linux --target=arm-linux --without-gtk --without-gthread --without-libjpeg --without-zlib --without-libpng --without-libtiff --without-libjasper --without-ffmpeg --without-raw1394 --without-v4l2 --without-python --prefix=/Project/OpenCV
 -> CXX= Crosscompiler g++ path
 -> --prefix= install path

[root@localhost opencv-1.0.0]# make
[root@localhost opencv-1.0.0]# make install


3. OpenCV 환경 설정

  1) /etc/ld.so.conf 에 prefix의 경로를 추가시킨 후 ldconfig -v 로 링킹 정보를 다시 읽어온다.
  2) /etc/profile 혹은 개인이 쓰는 환경 변수에 (빨간색은 prefix 경로) 다음 내용을 추가시켜준다.
-> export LD_LIBRARY_PATH=/Project/OpenCV/lib
-> export PKG_CONFIG_PATH=/Project/OpenCV/lib/pkgconfig


4. OpenCV 보드에 설치

  1) share 폴더를 제외한 나머지 폴더를 압축시켜 작업의 편의성을 위해 linux 에 설치한 경로와 똑같이 보드에 카피해 준다.

두 점 사이의 각도 계산



OpenCV 를 이용, 빨강, 검정 두 점을 인식하고 두 점 사이의 각도와 그 중심을 계산하여 출력하는 화면과 소스.

오브젝트의 방향성과 위치를 인식할 수 있게 되었다.

#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <math.h>


void main()
{
double redmin_val, redmax_val;
double blkmin_val, blkmax_val;
CvPoint redmin_loc, redmax_loc;
CvPoint blkmin_loc, blkmax_loc;
CvPoint line_start, line_end, center;
CvSize reddst_size;
CvSize blkdst_size;

IplImage* src_img = 0;  //
CvCapture* capture = cvCaptureFromCAM(0);  //
cvGrabFrame( capture );
src_img = cvRetrieveFrame( capture );
IplImage* redtmp_img = cvLoadImage("reddot.jpg", -1);
IplImage* blktmp_img = cvLoadImage("blkdot.jpg", -1);
reddst_size = cvSize( src_img->width - redtmp_img->width+1, src_img->height - redtmp_img->height+1 );
blkdst_size = cvSize( src_img->width - blktmp_img->width+1, src_img->height - blktmp_img->height+1 );

IplImage* reddst_img = cvCreateImage( reddst_size , IPL_DEPTH_32F, 1 );
IplImage* blkdst_img = cvCreateImage( blkdst_size , IPL_DEPTH_32F, 1 );

cvNamedWindow( "Vision Test", 0 );
cvNamedWindow( "Vision Test#2", 0);
cvResizeWindow( "Vision Test", 640, 480 );
cvResizeWindow( "Vision Test#2", 640, 480 );
while(1)
{
cvGrabFrame( capture );
src_img = cvRetrieveFrame( capture );
cvMatchTemplate(src_img, redtmp_img, reddst_img, CV_TM_CCOEFF_NORMED);
cvMatchTemplate(src_img, blktmp_img, blkdst_img, CV_TM_CCOEFF_NORMED);
cvMinMaxLoc(reddst_img, &redmin_val, &redmax_val, &redmin_loc, &redmax_loc, NULL);
cvMinMaxLoc(blkdst_img, &blkmin_val, &blkmax_val, &blkmin_loc, &blkmax_loc, NULL);
cvRectangle(src_img, redmax_loc, cvPoint(redmax_loc.x + redtmp_img->width, redmax_loc.y + redtmp_img->height), CV_RGB(255,0,0), 1);
cvRectangle(src_img, blkmax_loc, cvPoint(blkmax_loc.x + blktmp_img->width, blkmax_loc.y + blktmp_img->height), CV_RGB(255,0,0), 1);
line_start = cvPoint(blkmax_loc.x + (blktmp_img->width)/2 , blkmax_loc.y + (blktmp_img->height)/2);
line_end = cvPoint(redmax_loc.x + (redtmp_img->width)/2 , redmax_loc.y + (redtmp_img->height)/2);
center = cvPoint((line_start.x + line_end.x)/2, (line_start.y + line_end.y)/2);
cvLine(src_img, line_start, line_end, CV_RGB(255,0,0));
cvCircle(src_img, center, 30, CV_RGB(0,0,255), 3);
int dx = line_end.x - line_start.x;
int dy = line_end.y - line_start.y;

double PI=3.14;
double rad= atan2(dx, dy);
double degree = (rad*180)/PI;
printf("센터 : X = %d, Y = %d\t\t각도 : %.0lfº\n", center.x, center.y, degree);
cvShowImage( "Vision Test", src_img );
cvShowImage( "Vision Test#2", reddst_img );
if( cvWaitKey(10) >= 0 ) break;
}

cvReleaseCapture( &capture );
cvReleaseImage ( &src_img );
cvReleaseImage ( &redtmp_img );
cvReleaseImage ( &blktmp_img );
cvReleaseImage ( &reddst_img );
cvReleaseImage ( &blkdst_img );
cvDestroyAllWindows();
}

Cam edge 처리 소스. ( 출처 ::: OpenCV Korea )

#include <cv.h>
#include <highgui.h>

void main()
{
cvNamedWindow( "T9-camera", 0 );

IplImage* image = 0;
CvCapture* capture = cvCaptureFromCAM(0);
cvGrabFrame( capture );
image = cvRetrieveFrame( capture );

IplImage* gray=cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
IplImage* dst =cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);

dst->origin=1;
        
while(1) {
cvGrabFrame( capture );
image = cvRetrieveFrame( capture );
cvCvtColor( image, gray, CV_BGR2GRAY );
cvCanny(gray, dst, 160, 120);
cvShowImage( "T9-camera", dst );
 
if( cvWaitKey(10) >= 0 ) break;
}
cvReleaseCapture( &capture );
cvDestroyWindow( "T9-camera" );
}


OpenCV Korean site

http://www.opencv.co.kr/