정말죄송하지만..소스분석을좀 부탁해도될까요
카메라 소스거든요?
근데 제가 C를 잘몰르거든요..
근데 프로젝트를 갑자기 맞는바람에.
정말 내일까지 분석해가야는데.공부해서 하기엔
정말 불가능할꺼같아서 이렇게 염치불구하고
고수님들께 부탁드립니다..
=======================================
#include <linux/config.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/param.h>
#include <asm/ioctl.h>
#include <linux/signal.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#define GPIO_MAJOR 240
#define GPIO_NAME "CAMERA"
#define FLAG_ADDRESS 0xf1820000
#define SRAM_ADDRESS 0xf1830000
#define FLAG_ADDRESS_RANGE 2
#define SRAM_ADDRESS_RANGE 153600
#define IRQ_CMOS IRQ_GPIO(27)
static void cmos_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static pid_t id;
unsigned int *pFlag;
unsigned int *pSRAM;
unsigned short ycbcr422[76800];
unsigned short frameinfo;
unsigned short pFlagTRUE=0;
unsigned short rgb[76800];
unsigned char edgeFlag = 0;
#define EDGEFLAG _IO(0xbd,0)
static void cmos_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int i,j,k,l;
int Y1,Y2,Cb1,Cr1=0,Cr2=0;
int r,g,b;
disable_irq(IRQ_CMOS);
*pFlag = 0x00;
memcpy(ycbcr422,pSRAM,76800*2);
k=0; l=0; Cr1=0; Cr2=0;
if(edgeFlag) {
for(j=0;j<239;j++){
for(i=0;i<319;i++) {
Y1 = ycbcr422[k+1] - ycbcr422[k];
Y2 = ycbcr422[k+320] - ycbcr422[k++];
Y1 = Y1*Y1;
Y2 = Y2*Y2;
r = (Y1 > 16777216) ? 0xff00 : 0;
g = (Y2 > 16777216) ? 0xff00 : 0;
rgb[l++] = (r&0xf800)|(g&0xf800)|((r>>5)&0x7e0)|((g>>5)&0x7e0)|((r>>11)&0x1f)|((g>>11)&0x1f);
}
l++;
k++;
}
}else
{
for(j=0;j<240;j++)
for(i=0;i<320;i+=2){
// Cr1 = j ? Cr2 : (ycbcr422[k+2] & 0xff)-128; 속도 향상을 위해...
Y1 = (ycbcr422[k] & 0xff00);
Cb1= (ycbcr422[k++] & 0xff) - 128;
Y2 = (ycbcr422[k] & 0xff00);
Cr2= (ycbcr422[k++] & 0xff) - 128;
r = Y1 + 351*Cr1;
g = Y1 - 179*Cr1 - 86*Cb1;
b = Y1 + 443*Cb1;
r = r>0xff00 ? 0xff00 : r<0 ? 0x0: r;
g = g>0xff00 ? 0xff00 : g<0 ? 0x0: g;
b = b>0xff00 ? 0xff00 : b<0 ? 0x0: b;
rgb[l++] = (r&0xf800) | ((g>>5)&0x7e0) | ((b>>11)&0x1f);
r = Y2 + 351*Cr2;
g = Y2 - 179*Cr2 - 86*Cb1;
b = Y2 + 443*Cb1;
r = r>0xff00 ? 0xff00 : r<0 ? 0x0: r;
g = g>0xff00 ? 0xff00 : g<0 ? 0x0: g;
b = b>0xff00 ? 0xff00 : b<0 ? 0x0: b;
rgb[l++] = (r&0xf800) | ((g>>5)&0x7e0) | ((b>>11)&0x1f);
}
}
kill_proc(id,SIGUSR2,1);
}
ssize_t cis_write(struct file *inode, const char *gdata, size_t length, loff_t *off_what)
{
get_user(id,(int *)gdata);
enable_irq(IRQ_CMOS);
return length;
}
ssize_t cis_read(struct file *flip, char *buf, size_t count, loff_t *l)
{
copy_to_user(buf,rgb,153600);
return 153600;
}
static int cis_ioctl(struct inode *m_inode, struct file *mfile, unsigned int cmd, unsigned long gdata)
{
switch(cmd) {
case EDGEFLAG:
edgeFlag = edgeFlag ? 0: 1;
break;
default:
break;
}
return 0;
}
static int cis_open(struct inode *inode, struct file *filp){
int res;
unsigned int gafr;
//gafr = 0x3; //gpio16
gafr = (0x3 << 22); //gpio27
GAFR0_U &= ~gafr;
gafr = 0x1;
GPDR1 &= ~gafr;
GPDR(IRQ_TO_GPIO_2_80(IRQ_CMOS)) &= ~GPIO_bit(IRQ_TO_GPIO_2_80(IRQ_CMOS));
set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(IRQ_CMOS),GPIO_FALLING_EDGE);
res = request_irq(IRQ_CMOS,&cmos_interrupt,SA_INTERRUPT,"CMOS",NULL);
if(res < 0){
printk(KERN_ERR "%s: Request for IRQ %d failed\n",__FUNCTION__,IRQ_CMOS);
return -1;
}
pFlag = (unsigned int *)FLAG_ADDRESS;
pSRAM = (unsigned int *)SRAM_ADDRESS;
MOD_INC_USE_COUNT;
return 0;
}
static int cis_release(struct inode *inode, struct file *filp)
{
free_irq(IRQ_CMOS,NULL);
disable_irq(IRQ_CMOS);
MOD_DEC_USE_COUNT;
return 0;
}
static struct file_operations cis_fops = {
read: cis_read,
write: cis_write,
ioctl: cis_ioctl,
open: cis_open,
release: cis_release,
};
int init_module(void){
int result;
result = register_chrdev(GPIO_MAJOR,"GPIO INTERRUPT",&cis_fops);
if(result < 0) {
printk(KERN_WARNING"Can't get major %d\n",GPIO_MAJOR);
return result;
}
if(!check_region(FLAG_ADDRESS,FLAG_ADDRESS_RANGE))
request_region(FLAG_ADDRESS,FLAG_ADDRESS_RANGE,GPIO_NAME);
else
{
printk("driver : unable to use the address\n");
unregister_chrdev(GPIO_MAJOR ,GPIO_NAME);
return -1;
}
if(!check_region(SRAM_ADDRESS,SRAM_ADDRESS_RANGE))
request_region(SRAM_ADDRESS,SRAM_ADDRESS_RANGE,GPIO_NAME);
else
{
printk("driver : unable to use the address\n");
unregister_chrdev(GPIO_MAJOR ,GPIO_NAME);
return -1;
}
return 0;
}
void cleanup_module(void){
release_region(FLAG_ADDRESS,FLAG_ADDRESS_RANGE);
release_region(SRAM_ADDRESS,SRAM_ADDRESS_RANGE);
if(unregister_chrdev(GPIO_MAJOR ,GPIO_NAME))
printk("driver : %s DRIVER CLEANUP FALLED\n",GPIO_NAME);
return;
}
어디가 이해가 되지 않는 다는 것인가요??
어디가 이해가 되지 않는 다는 것인가요??
ㅇ
어느부분그런게아니구요..
아ㅇㅖ 소스를 볼줄모르는데요..ㅠㅠ
정말시간있으시면 어떻게해서 어떻게 부분적으로
설명을해주시면안댈까요,사람한명 돕는다치구요..
부탁해요..
알파벳도 모르는데 어찌 영문학 작품 평을 쓸 수 있겠습니까.기초부터
알파벳도 모르는데 어찌 영문학 작품 평을 쓸 수 있겠습니까.
기초부터 시작하시는 게 맞을 듯...
-----
http://monpetit.posterous.com/
http://monpetit.tistory.com/
아..
알겟습니다.
쉬운방법으로 받아먹으려고만
제 생각이 짧았습니다.
즐거운 하루되세요.
device driver 소스같은데요.해당 칩의 스펙과 회로도를
device driver 소스같은데요.
해당 칩의 스펙과 회로도를 같이 보시면서 분석하시는게 좋을 것 같습니다.
소스만 봐서는
이런 구문을 이해할 수가 없습니다;;
[니 칼은 니가 갈아라]
소스를 보면 대충 CMOS에서 rgb 값을 얻어 오는 디바이스 드라이버
소스를 보면 대충 CMOS에서 rgb 값을 얻어 오는 디바이스 드라이버 같은데요.
실제 중요한 부분은 별로 없는것 같습니다. 우선 CMOS 스펙을 봐야 할텐데요.
cmos_interrupt 는 SRAM에서 cr,y,cb 값을 가지고 rgb 변환을 하도록 하는데
데이터 연산이니까, 이건 데이터 시트 보면 답이 나오겠구요.
근데 EdgeFlag의 의도가 약간 의심 스럽네요.
write에서 enable_irq를 한거 보니, 매번 인터럽트때 마다 APP에서 데이터를 가져오기 위해 동기화 시키려고 하는것인지.. interrupt 하고 write의 처리의도가 무엇인지.. 생각해보셔야 할것입니다. 왜저렇게 짰는지?? -_-;;;
read는 rgb 읽어 오는 거구요. 아마도 APP에서는 open 후에 read로 rgb값을 얻어 오려는것 같습니다.
ioctl 에서 edgeflag를 설정 하는데, 이게 320x240 이미지 가지고 어떻게 하려는지 의도가.. 이미지의 edge를 잡으려는것 인지.. 대충봐서는 알수가 없습니다. 정확한 의도를 파악해야 겠군요.
open에서 GAFR 을 사용했는데.. 아마도 심볼을 보니 xscale 인가 보죠?? 아닌가?? 하여튼 alternative function 레지스터의 값을 변경해서 인터럽트 핀으로 사용하기 위함이고.. GPDR도 설정했는데 인터럽트 소스로 쓸려고 입력으로 바꾼거 같구요.. 아마도 Set_GPIO_IRQ_Edge에 GPIO 방향선택이 들어가 있을 터인데.. 이함수는 커널 보면 될것입니다.. 만들기 나름이니까요..
pflag 하고 psram의 주소 잡아주고 끝나네요.
init_module과 cleanup_module은 리눅스 드라이버 책 보시면 이해가 될것이구요. 실제 대세에는 영향이 없습니다. 목적이 rgb값을 읽어오는 것이니까요.
이상 허접 답변이었습니다.. :oops:
소스보다는 먼저
한글을 제대로 배우셔야 할 듯..
소스분석도 안 해 드리면서 엉뚱한 걸로 댓글을 달아서 죄송하긴 하지만
대강이렇습니다.
//CMOS에서 rgb값을 얻어오는 디바이스 드라이버
//SRAM에서 cr, y, cb값을 가지고 rgb변환을 하도록한다.
#include <linux/config.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/param.h>
#include <asm/ioctl.h>
#include <linux/signal.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#define GPIO_MAJOR 240
#define GPIO_NAME "CAMERA"
#define FLAG_ADDRESS 0xf1820000
#define SRAM_ADDRESS 0xf1830000
#define FLAG_ADDRESS_RANGE 2
#define SRAM_ADDRESS_RANGE 153600
#define IRQ_CMOS IRQ_GPIO(27)
static void cmos_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static pid_t id;
unsigned int *pFlag;
unsigned int *pSRAM;
unsigned short ycbcr422[76800];
unsigned short frameinfo;
unsigned short pFlagTRUE=0;
unsigned short rgb[76800];
unsigned char edgeFlag = 0;
#define EDGEFLAG _IO(0xbd,0)
static void cmos_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
// 인터럽트
int i,j,k,l;
int Y1,Y2,Cb1,Cr1=0,Cr2=0;
int r,g,b;
disable_irq(IRQ_CMOS);
*pFlag = 0x00;
memcpy(ycbcr422,pSRAM,76800*2);
k=0; l=0; Cr1=0; Cr2=0;
if(edgeFlag)
// 엣지 플레그가 1일 경우
{
for(j=0;j<239;j++){
// 240 pixel
for(i=0;i<319;i++) {
// 320 pixel
Y1 = ycbcr422[k+1] - ycbcr422[k];
Y2 = ycbcr422[k+320] - ycbcr422[k++];
Y1 = Y1*Y1;
Y2 = Y2*Y2;
r = (Y1 > 16777216) ? 0xff00 : 0;
g = (Y2 > 16777216) ? 0xff00 : 0;
rgb[l++] = (r&0xf800)|(g&0xf800)|((r>>5)&0x7e0)|((g>>5)&0x7e0)|((r>>11)&0x1f)|((g>>11)&0x1f);
}
l++;
k++;
}
}else
// 엣지 플레그가 0일 경우
{
for(j=0;j<240;j++)
for(i=0;i<320;i+=2){
// Cr1 = j ? Cr2 : (ycbcr422[k+2] & 0xff)-128; 속도 향상을 위해...
Y1 = (ycbcr422[k] & 0xff00);
Cb1= (ycbcr422[k++] & 0xff) - 128;
Y2 = (ycbcr422[k] & 0xff00);
Cr2= (ycbcr422[k++] & 0xff) - 128;
r = Y1 + 351*Cr1;
g = Y1 - 179*Cr1 - 86*Cb1;
b = Y1 + 443*Cb1;
r = r>0xff00 ? 0xff00 : r<0 ? 0x0: r;
g = g>0xff00 ? 0xff00 : g<0 ? 0x0: g;
b = b>0xff00 ? 0xff00 : b<0 ? 0x0: b;
rgb[l++] = (r&0xf800) | ((g>>5)&0x7e0) | ((b>>11)&0x1f);
r = Y2 + 351*Cr2;
g = Y2 - 179*Cr2 - 86*Cb1;
b = Y2 + 443*Cb1;
r = r>0xff00 ? 0xff00 : r<0 ? 0x0: r;
g = g>0xff00 ? 0xff00 : g<0 ? 0x0: g;
b = b>0xff00 ? 0xff00 : b<0 ? 0x0: b;
rgb[l++] = (r&0xf800) | ((g>>5)&0x7e0) | ((b>>11)&0x1f);
}
}
kill_proc(id,SIGUSR2,1);
}
ssize_t cis_write(struct file *inode, const char *gdata, size_t length, loff_t *off_what)
{
get_user(id,(int *)gdata);
// gdata 의 사이즈만큼 *gdata을 id로 복사 한다.
enable_irq(IRQ_CMOS);
// IRQ_CMOS 허가
return length;
}
ssize_t cis_read(struct file *flip, char *buf, size_t count, loff_t *l)
{ //rgb를 읽어 오는것 open후에도 rgb값을 얻어오려는 것같음.
copy_to_user(buf,rgb,153600);
// rgb에서 buf로 153600 만큼 복사 한다.
return 153600;
}
static int cis_ioctl(struct inode *m_inode, struct file *mfile, unsigned int cmd, unsigned long gdata)
{//디바이스드라이브가 제대로 적재되고 나서 설정값을 바꿀필요가 있을때 loctl함수를 부른다.
switch(cmd) {
// cmd 판별
case EDGEFLAG:
// cmd 가 EDGEFLAG 일경우
////////////////////////
edgeFlag = edgeFlag ? 0: 1;
// edgeFlag 가 1일 경우 0을 0일 경우 1을 넣는다.
break;
default:
break;
}
return 0;
}
static int cis_open(struct inode *inode, struct file *filp){
int res;
unsigned int gafr;
//gafr = 0x3; //gpio16
gafr = (0x3 << 22); //gpio27
GAFR0_U &= ~gafr;
gafr = 0x1;
GPDR1 &= ~gafr;
GPDR(IRQ_TO_GPIO_2_80(IRQ_CMOS)) &= ~GPIO_bit(IRQ_TO_GPIO_2_80(IRQ_CMOS));
// gpio의 입출력 방향 설정
set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(IRQ_CMOS),GPIO_FALLING_EDGE);
// gpio의 IRQ 를 FALLING_EDGE일때 동작 설정
res = request_irq(IRQ_CMOS,&cmos_interrupt,SA_INTERRUPT,"CMOS",NULL);
// 인터럽트를 등록
//request_irq이함수로 인터럽트 사용시 이것을 사용하겠다고 요청.
if(res < 0){
// 실패시 -1 리턴
printk(KERN_ERR "%s: Request for IRQ %d failed\n",__FUNCTION__,IRQ_CMOS);
return -1;
}
pFlag = (unsigned int *)FLAG_ADDRESS;//pFlag의 주소를 잡아준다.
pSRAM = (unsigned int *)SRAM_ADDRESS;//pSRAM의 주소를 잡아준다.
MOD_INC_USE_COUNT;
return 0;
}
static int cis_release(struct inode *inode, struct file *filp)
{
// 드라이버 정리
free_irq(IRQ_CMOS,NULL);
disable_irq(IRQ_CMOS);
MOD_DEC_USE_COUNT;
return 0;
}
static struct file_operations cis_fops = {//커널에서는 어떤 디바이스라도
//파일과 같은 접근 하므로 구조체로 정의.
read: cis_read,
write: cis_write,
ioctl: cis_ioctl,
open: cis_open,
release: cis_release,
};
int init_module(void){
// 드라이버 초기화
int result;
result =register_chrdev(GPIO_MAJOR,"GPIO INTERRUPT",&cis_fops);
// 문자 디바이스 드라이버를 커널에 등록
//드라이버 등록 함수로 주장치번호 디바이스이름 파일조작함수인터페이스를 등록한다.
if(result < 0) {
// 등록 실패시
printk(KERN_WARNING"Can't get major %d\n",GPIO_MAJOR);
return result;
}
if(!check_region(FLAG_ADDRESS,FLAG_ADDRESS_RANGE))
//디바이스가 사용랗 번지주소가 유효한지 검사하는 함수.
// 영역 검사
// 영역이 사용중이 아닐때
// 영역 요청
request_region(FLAG_ADDRESS,FLAG_ADDRESS_RANGE,GPIO_NAME);
//주소가 유효하다면 request_region으로 이주소를 점유
else
{
// 사용중일때?
printk("driver : unable to use the address\n");
unregister_chrdev(GPIO_MAJOR ,GPIO_NAME);
return -1;
}
if(!check_region(SRAM_ADDRESS,SRAM_ADDRESS_RANGE))
// SRAM 영역 검사
// 영역이 사용중이 아닐때
// 영역 요청
request_region(SRAM_ADDRESS,SRAM_ADDRESS_RANGE,GPIO_NAME);
else
{
// 사용 중일때?
printk("driver : unable to use the address\n");
unregister_chrdev(GPIO_MAJOR ,GPIO_NAME);
return -1;
}
return 0;
}
void cleanup_module(void){
// 클린업 함수
release_region(FLAG_ADDRESS,FLAG_ADDRESS_RANGE);//주소유효를 해제
release_region(SRAM_ADDRESS,SRAM_ADDRESS_RANGE);
if(unregister_chrdev(GPIO_MAJOR ,GPIO_NAME))//장치 특수 번호를 해제하여 커널이
//디바이스를 사용하지않도록한다.
printk("driver : %s DRIVER CLEANUP FALLED\n",GPIO_NAME);
return;
}
댓글 달기