반응형
이전 글 먼저 하고 오세영~
우분투로 넘어와서 이전 글에서 작성한 코드들 좀만 더 함수화하겠음.
커널 시스템 콜 함수 코드임.
ubuntu@ubuntu8:~/pi_bsp/kernel/linux/kernel$ cp test_mysyscall.c test_mysyscall.c_v2
#include <linux/kernel.h>
#include <linux/gpio.h>
#define OFF 0
#define ON 1
#define GPIOLEDCNT 8
int gpioLed[] = {6,7,8,9,10,11,12,13};
int gpioLedInit(void);
void gpioLedSet(long val);
void gpioLedFree(void);
asmlinkage long sys_mysyscall(long val)
{
gpioLedInit();
gpioLedSet(val);
gpioLedFree();
return 1;
}
int gpioLedInit(void)
{
int i;
int ret = 0; //함수들의 리턴값 저장용 변수
char gpioNameBuff[10];//애는 스택에서 선언하는거고
for(i=0;i<GPIOLEDCNT;i++)
{
sprintf(gpioNameBuff,"led%d",i);
ret = gpio_request(gpioLed[i],gpioNameBuff);
if(ret < 0){
printk("Failed gpio_request() gpio%d error \n",6);
return ret;
}
ret = gpio_direction_output(gpioLed[i],OFF);
if(ret < 0){
printk("Failed gpio_direction_output() gpio%d error \n",6);
return ret;
}
}
}
void gpioLedSet(long val)
{
int i;
for(i=0;i<GPIOLEDCNT;i++)
{
gpio_set_value(gpioLed[i],(val>>i) & 0x1);//입력을 0xff처럼 받아서 1비트씩 비교해서 val를 써주면 됨
}
}
void gpioLedFree(void)
{
int i;
for(i=0;i<GPIOLEDCNT;i++)
{
gpio_free(gpioLed[i]);
}
}
리눅스 디바이스 드라이버 단에선 c 코드 작성할 때 입력값 없으면 void 넣어줘야 됨. warning 나옴
작성 끝났으니, 빌드하고 파일 넘기고
라즈베리파이에서도 파일 받아서 폴더에 넣어주고 재부팅합시다
잘됬죠?
gpio 버튼을 통해 led를 제어하는 코드
1. kernel system call 함수 부분
#include <linux/kernel.h>
#include <linux/gpio.h>
#define OFF 0
#define ON 1
#define GPIOLEDCNT 8
#define GPIOKEYCNT 8
int gpioLed[] = {6,7,8,9,10,11,12,13};
int gpioKey[] = {16,17,18,19,20,21,22,23};
int gpioLedInit(void);
int gpioKeyInit(void);
unsigned long gpioKeyGet(void);
void gpioKeyFree(void);
void gpioLedSet(long val);
void gpioLedFree(void);
asmlinkage long sys_mysyscall(long 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 gpioNameBuff[10];//애는 스택에서 선언하는거고
for(i=0;i<GPIOLEDCNT;i++)
{
sprintf(gpioNameBuff,"led%d",i);
ret = gpio_request(gpioLed[i],gpioNameBuff);
if(ret < 0){
printk("Failed gpio_request() gpio%d error \n",6);
return ret;
}
ret = gpio_direction_output(gpioLed[i],OFF);
if(ret < 0){
printk("Failed gpio_direction_output() gpio%d error \n",6);
return ret;
}
}
return 1;
}
void gpioLedSet(long val)
{
int i;
for(i=0;i<GPIOLEDCNT;i++)
{
gpio_set_value(gpioLed[i],(val>>i) & 0x1);//입력을 0xff처럼 받아서 1비트씩 비교해서 val를 써주면 됨
}
}
void gpioLedFree(void)
{
int i;
for(i=0;i<GPIOLEDCNT;i++)
{
gpio_free(gpioLed[i]);
}
}
int gpioKeyInit(void)
{
int i;
int ret = 0; //함수들의 리턴값 저장용 변수
char gpioNameBuff[10];//애는 스택에서 선언하는거고
for(i=0;i<GPIOKEYCNT;i++)
{
sprintf(gpioNameBuff,"key%d",i);
ret = gpio_request(gpioKey[i],gpioNameBuff);
if(ret < 0){
printk("Failed gpio_request() gpio%d error \n",6);
return ret;
}
ret = gpio_direction_input(gpioKey[i]);
if(ret < 0){
printk("Failed gpio_direction_output() gpio%d error \n",6);
return ret;
}
}
return 1;
}
unsigned long gpioKeyGet(void)
{
unsigned long key_value=0x00;
int i;
for(i=0;i<GPIOKEYCNT;i++)
{
key_value = (key_value) | gpio_get_value(gpioKey[i])<<i;
}
return key_value;
}
void gpioKeyFree(void)
{
int i;
for(i=0;i<GPIOKEYCNT;i++)
{
gpio_free(gpioKey[i]);
}
}
빌드해서 파이에 zImage 넘겨주고
라즈베리파이 재부팅~
2. application 부분
pi@pi08:~/systemcall_test$ vi syscall_app_v2_ledkey.c
#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;
}
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;
}
컴파일하고 실행~
vi 명령어
cw해서 커서 뒤에 있는 한 단어 삭제 하고 문자들을 넣어줄수 있는데
:%s 모든 문자열 중에
/gpioLedCnt 이 문자를
/GPIOLEDCNT 이 문자로 바꾸겠다.
:%s /gpioLedCnt/GPIOLEDCNT
반응형
'RaspberryPi' 카테고리의 다른 글
[Raspberry Pi Kernel] Kernel의 시스템 콜 함수를 활용한 GPIO LED 제어 (0) | 2024.02.16 |
---|---|
[Raspberry Pi Kernel] Kernel menuconfig로 GPIO enable하고 다시 LCD 켜기 (0) | 2024.02.16 |
[RaspberryPi Kernel] Ubuntu에서 Raspberry Pi Kernel system call 함수 구현 (0) | 2024.02.15 |
[RaspberryPi4 Kernel] Ubuntu에서 BCM2711 커널 빌드해서 올리기 (0) | 2024.02.15 |
[Raspberry Pi] 작업한 이미지 복제하기 (2) | 2024.02.02 |