2009년 12월 21일 월요일
QT4 with OpenCV, How to convert QImage to IplImage
2009년 12월 20일 일요일
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
N.T.C 사의 AM-CS2P (Stepping motor driver)
![](http://www.newtc.co.kr/product_img/AM-CS2_1.jpg)
▶ AM-CS2P (스테핑 모터 구동 모듈) 소개
![](http://www.newtc.co.kr/product_img/AM-CS2_2.jpg)
▶ AM-CS2P (스테핑 모터 구동 모듈) 제어 신호
![](http://www.newtc.co.kr/product_img/AM-CS2_3.jpg)
N.T.C 사의 AB-M128-B (MCU : ATMega128)
![](http://www.newtc.co.kr/product_img/AB-M128-B_1.jpg)
▶ AB-M128-B 개발 보드 특징
![](http://www.newtc.co.kr/product_img/AB-M128-B_2.jpg)
▶ 포트 커넥터 (PORTA ~ PORTF 까지 출력)
![](http://www.newtc.co.kr/product_img/KD-128PRO_3.jpg)
▶ AB-M128-B 사진
![](http://www.newtc.co.kr/product_img/AB-M128-B_5.jpg)
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 간 통신 회로도
![](http://pds15.egloos.com/pds/200911/02/34/f0088634_4aee5e3dbfa5e.gif)
● RS232 cable pin map
![](http://pds16.egloos.com/pds/200911/02/34/f0088634_4aee5e4f92059.gif)
ATMega128 Datasheet & Circuit Diagram
-> datasheet.pdf
ROM : AT29C256
-> datasheet.pdf
![](http://pds15.egloos.com/pds/200911/17/34/f0088634_4b023e8b58536.jpg)
QT4 with OpenCV, How to convert IplImage to QImage
{
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);
}
형 변환
2. char[]
3. int
4. long
QString aaa;
1. aaa.ascii()[0];
2. aaa.ascii()(;
3. aaa.toInt();
3. aaa.toLong();
int 형을 QString으로 변경 시키는 방법
int b = 10;
a = a.setNum(b);
char형을 QString으로 변경 시키는 방법
strcpy(szFullPath, "world");
QString data;
QString how;
data = "Hello ";
how = data + QString(szFullPath);
Tslib 1.0
▶ Tslib 1.0
./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)
./configure -embedded arm -shared -thread -debug -no-cups -continue -qt-mouse-linuxtp -qt-zlib -qt-gif -qt-libpng -no-libmng -qt-libjpeg
ZigBee, ATmega128 과 PC 연결 방법.
![](http://pds16.egloos.com/pds/200911/19/34/f0088634_4b041754bef08.jpg)
-> 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)
![](http://pds17.egloos.com/pds/200911/19/34/f0088634_4b041881a2ece.jpg)
● XBee Datasheet
-> Data-sheet-max-stream.pdf
● XBee Pin map
![](http://pds17.egloos.com/pds/200911/18/34/f0088634_4b03cb54037b3.jpg)
● 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와 같도록 매크로 정의 |
Linux Kernel API
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 와 연동하기
OpenCV, EZ-X5에 포팅하기
[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
3. OpenCV 환경 설정
1) /etc/ld.so.conf 에 prefix의 경로를 추가시킨 후 ldconfig -v 로 링킹 정보를 다시 읽어온다.
1) share 폴더를 제외한 나머지 폴더를 압축시켜 작업의 편의성을 위해 linux 에 설치한 경로와 똑같이 보드에 카피해 준다.
두 점 사이의 각도 계산
![](http://pds15.egloos.com/pmf/200912/16/34/f0088634_4b289ec5d9599.jpg)
Cam edge 처리 소스. ( 출처 ::: OpenCV Korea )
![](http://pds16.egloos.com/pds/200912/06/34/f0088634_4b1a75cc88b8d.jpg)