글

라벨이 device layer인 게시물 표시

mkfs.fat Device or resource busy 에러 해결법

이미지
 리눅스에서 SD 카드를 포맷할 때 아래와 같이 "Device or resource busy"에러를 출력하며 포맷이 되지 않는 경우가 있다. mkfs.fat: unable to open /dev/mmcblk0p1: Device or resource busy 해결법을 찾아보았다. 이 문제의 원인은  1. 파티션 dev path 가 맞지 않거나,  2. umount가 완전히 이루어 지지 않았거나,  3. mbr파티션에 문제가 있어 발생한다고 한다.  파티션에 문제가 있는 경우 fdisk를 사용하면 문제를 해결할 수 있다. umount에 문제가 있는 경우, umount할 때 -l 옵션이 사용되는 경우 umount 명령이 끝나도 커널 내부에서 리소스가 계속 사용될 가능성이 있다고 한다.  # umount -l /mnt/mmc umount2("/mnt/mmc",MNT_DETACH); 이런 경우 일정 시간 후 다시 시도하면 에러 없이 포맷이 되는 경우가 있다. 또, umount 가 되지 않을 때 "lsof" , "fuser" 명령어를 사용하여 어떤 프로세스가 mmc를 사용하고 있는지도 확인 가능하다. * lsof에서 사용 내역이 없다고 나와도, fuser에서 나올수 있다.  lsof, fuser 명령에서도 mmc를 사용하는 프로세스가 없는 경우에도 "Device or resource busy"에러가 발생할 경우, umount에 -lf 옵션을 두어 강제로 언마운트 후 SD 카드를 포맷하면 "Device or resource busy"에러가 나타나지 않을 확률이 높아진다. # umount -lf /mnt/mmc umount2("/mnt/mmc",MNT_DETACH | MNT_FORCE); * fat32에서는 "-f","...

embedded Linux .so 라이브러리 로드 에러 간단한 디버깅 해결 방법

Linux에서 so 라이브러리를 로드 하지 못하고 에러를 출력할 경우 다음과 같은 방법으로 해결할 수 있다 $ ./a.out ./a.out: error while loading shared libraries: xxx.so: cannot open shared object file: No such file or directory 1. xxx.so 파일 형식 확인  file 명령어를 사용하여 so 파일과 실행 파일의 elf 형식, process 타입을 확인한다. 서로 다른 프로세서나 다른 타입의 툴체인에서 빌드 된 바이너리는 혼용할 수 없다.  만약, so 파일의 elf 형식이 (GNU/Linux) 이고 실행파일의 형식이 SYSV인 경우, 실행파일 빌드 시 -D_GNU_SOURCE 를 추가하고 빌드하면 so 파일을 로드 할 수 있다. 2. xxx.so 파일 이름 확인  실제 사용하고 싶은 라이브러리와 에러 메시지의 so 파일 이름을 확인한다.   간혹 so 파일의 path가 같이 출력되거나 so파일 뒤에 ".0" 이 붙는 등 이름이 다른 경우가 있는데, 이는 so 파일 빌드 시 -soname 옵션을 사용해 로드 할 so 파일의 이름을 그렇게 정했기 때문이다.  so 파일의 빌드 옵션을 수정하거나, ln 명령어를 사용해 링크를 만들어 시용하면 된다. $ ln -sf xxx.so.0 xxx.so 3. LD_LIBRARY_PATH 확인 LD_LIBRARY_PATH의 위치를 확인 후 해당 위치에 라이브러리가 존재하는지 확인한다. $ echo $LD_LIBRARY_PATH /Lib so 파일 위치를 추기하려면 LD_LIBRARY_PATH에 원하는 path를 추가하면 된다. $ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/xxx_path $...

insmod vmalloc: allocation failure 발생 해결법

이미지
임베디드 리눅스에서 insmod를 이용해 모듈을 로딩할 때 vmalloc allocation failure 에러를 출력하며 모듈이 로딩되지 않을 때의 해결방법은 아래와 같다. 1.  Vmalloc 메모리 체크 실제 사용되는 Vmalloc 메모리 용량을 확인한다. #cat /proc/meminfo | grep "Vmalloc" VmallocTotal: 516096 kB VmallocUsed:         0 kB VmallocChunk:       0 kB 만약 Vmalloc 메모리 용량이 적을 경우 bootargs의 vmalloc=<size>를 확인 후 용량을 늘려준다. vmalloc=512M 2. .modules 의 크기 위 1번을 사용해 vmalloc 메모리의 크기를 늘려도 해결되지 않을 경우, .modules의 크기를 늘려준다. .modules의 크기는 MODULES_VADDR의 크기를 조정하면 된다. MODULES_VADDR은 arm의 경우 arch/am/include/asm/memory.h에 정의되어 있다. 커널 버전에 따라 .config의 CONFIG_MODULES_AREA_SIZE을 변경하여 조정할 수도 있다. 8M의 경우 CONFIG_MODULES_AREA_SIZE=0x00800000 16M의 경우 CONFIG_MODULES_AREA_SIZE=0x01000000 관련 포스트 리눅스 디바이스 드라이버 기초와 예제

임베디드 리눅스 Starting Kernel 로그 출력 후 멈춤 현상이 있을때

임베디드 리눅스를 포팅하고 부팅 중 Staring Kernel 메시지 이후 아무런 로그 메시지가 출력되지 않고 멈추는 경우가 있다. 경험상 이런 경우 보통 Device Tree에서 GPIO설정이 잘못되었거나 파일시스템 설정이 잘못되어 rootfs를 마운트 하지 못해 발생하는 경우가 많았다. 확실히 하기 위해 로그 메시지를 레벨을 조정해 어디에서 부팅이 멈춘 것인지 확실히 해야 한다. 커널 로그 메시지 레벨은 kernel .config에서 LOGLEVEL을 수정하면 된다.  LOGLEVEL이 클수록 모든 로그 메시지를 출력한다.  https://man7.org/linux/man-pages/man2/syslog.2.html # # Kernel hacking # CONFIG_DEFAULT_MESSAGE_LOGLEVEL=7 만약, LOGLEVEL을 수정해도 아무런 로그 메시지가 나오지 않는다면, bootargs의 loglevel 값이 어떻게 설정되어 있는지 확인할 필요가 있다. loglevel도 클수록 모든 로그 메시지를 출력한다.

리눅스 디바이스 드라이버 기초와 예제

이미지
▢  디바이스 드라이버  디바이스 드라이버는 시스템이 지원하는 하드웨어를 사용자가 응용 프로그램에서 사용할 수 있도록 커널의 일부 영역을 사용하여 동작하는 일종의 프로그램이다.   리눅스에서 사용자가 커널 모드의 디바이스 드라이버를 사용하여 실제 하드웨어 디바이스에 접근하고자 할 때 아래 그림과 같은 추상적인 계층들을 통과해야 한다.    리눅스 사용자 관점에서 디바이스는 하나의 파일로 인식된다. 이런 파일들은 /dev 디렉토리에 위치하며, 이들을 디바이스 파일이라고 한다.    디바이스 드라이버는 문자/블록/네트워크 디바이스 드라이버 세 종류가 있으며, 각 디바이스는 주 번호(Major number)와 부 번호(Minor number)를 갖고 있다.  문자 디바이스 (Char Device) 자료의 순차성을 지닌 장치로 버퍼 캐쉬를 사용하지 않으며, 장치의 raw data를 사용자에게 제공한다. 시리얼, 키보드, 프린터, 마우스 등이 이에 속한다.  블록 디바이스 (Block Device) Radom access, 블록 단위의 입출력이 가능하고, 파일 시스템에 의해 mount 되어 관리되는 장치. 디스크, CD-ROM등이 이에 속한다.  네트워크 디바이스 (Network Device) 대응하는 장치 파일 없으며, 네트워크 통신을 통해 패킷을 송수신할 수 있는 장치. 이더넷 등이 이에 속한다.    ▢  커널 모듈 커널 모듈은 리눅스 커널이 부팅되어 동작 중일때도 동적으로 추가하거나 제거할 수 있는 커널의 구성요소이다. 디바이스 드라이버, 파일 시스템, 네트워크 프로토콜 등이 모듈로 제공된다.  커널 모듈은 커널 영역에서 동작한다. 일반 응용프로그램과 달리 main함수가 없...

Linux esp8266 driver c source code - AP 모드로 softAP

이미지
 임베디드 리눅스의 사용자 모드에서 동작하는 esp8266 드라이버를 만들고 있다. linux용 esp8266 드라이버 c source code - smartconfig Linux esp8266 driver c source code - client TCP, UDP Linux esp8266 driver c source code - TCP Server 본 포스트에서는 esp8266을 AP로 사용하는 SoftAP모드를 구현하고 테스트했다. SoftAP Mode ESP8266의 SoftAP 모드는 아래 커맨드를 사용하여 설정한다. AT+CWMODE_CUR=<mode> <mode>를 1로 하면 Station Mode, 2는 SoftAP Mode, 3이면 SoftAP+Station Mode이다. [note] 3번 SoftAP+Station 모드는 테스트해보지 못했다. SoftAP 설정 AT+CWSAP_CUR=<ssid>,<pwd>,<chl>,<ecn>[,<max conn>][,<ssid hidden>] AT+CWSAP_CUR 커맨드를 사용하면 AP의 SSID 및 패스워드, 채널, 암호화 방식 등을 설정할 수 있다. 파라미터  <ssid>: AP의 SSID. <pwd>: 패스워드, 8 ~ 64 바이트 ASCII.  <chl>: 채널 ID.  <ecn>: 암호화 방식, WEP는 지원하지 않는다. 0: OPEN 2: WPA_PSK 3: WPA2_PSK 4: WPA_WPA2_PSK  [<max conn>] (optional): 최대 연결 기기 수  [<ssid hidden>] (optional): SSID를 숨길지 여...

Linux esp8266 driver c source code - TCP Server

이미지
 임베디드 리눅스 환경에서 user mode에서 동작하는 esp8266 드라이버를 만드는 중이다. 이전 포스트에서 smartconfig와 client 모드에서의 TCP, UDP 연결에 대해 알아보고 구현했다.  linux용 esp8266 드라이버 c source code - smartconfig Linux esp8266 driver c source code - client TCP, UDP 이번 포스트에서는 TCP server 기능을 구현하고 예제를 통해 동작을 확인했다. ESP8266 TCP 서버 모드 ESP8266에서는 간단하게 AT+CIPSERVER 커맨드를 사용해 TCP 서버를 만들 수 있다. AT+CIPSERVER=<mode>[,<port>] 파라메터 <mode> : 0 이면 서버 종료, 1 이면 서버 생성 <port> : 포트 번호, 디폴트 값은 333이다. 원격 클라이언트에서 서버로 연결되면 ESP8266는 CONNECT 메세지를 보내온다.  서버를 반드시 multiple connection모드인 상태에서 사용해야 한다.  multiple connection모드는 AT+CIPMUX=1 커맨드를 사용하여 설정할 수 있다. 클라이언트 연결 닫기 서버에 연결된 클라이언트는 아래 AT 커맨드를 사용해 연결을 끊을 수 있다. AT+CIPCLOSE=<link ID> 데이터 읽고 쓰기 연결된 클라이언트와 데이터를 주고, 받는 방법은  Linux esp8266 driver c source code - client TCP, UDP  포스트의 데이터 전송과 데이터 읽기의 방식을 그대로 사용하면 된다.  ESP8266 Driver C Source esp8266.tcpserver.h esp8266.tcpserver.c ...

Linux esp8266 driver c source code - client TCP, UDP

이미지
 리눅스 환경에서 esp8266 드라이버를 만드는 중이다. 이전 포스트에서 smartconfig 기능까지 구현했었다. linux용 esp8266 드라이버 c source code - smartconfig 본 포스트에서는 client 모드로 TCP/UDP 통신 기능을 구현하고 예제를 통해 동작을 확인했다. SSL의 경우 esp8266에서는 지원한다고 되어있으나, 동작하지 않는 사이트가 많아 제외했다. esp8266 single/multiple connection mode 아래 명령어를 사용해 single/multiple 연결 모드를 설정할 수 있다.  Single Connection AT+CIPMUX= 0 multiple Connection AT+CIPMUX=1 Multiple Connection 모드인 경우 TCP/UDP 연결 command 및 데이터 메세지에 <link ID>가 붙어 어떤 link를 사용할지 구분할 수 있다.  esp8266에서는 0~4까지의 link ID를 지원한다. esp8266 TCP/UPD 연결 Single Connection  AT+CIPSTART=<type>,<remote IP>,<remote port>[,<TCP keep alive>] Multiple Connections  AT+CIPSTART=<link ID>,<type>,<remote IP>,<remote port>[,<TCP keep alive>] 파라미터 <type> : "TCP","UDP" <remote IP> : 연결하고자 하는 IP 주소 문자열이나 주소 문자열 <remote port> : 포트 번호 <TCP keep alive>  :...

linux용 esp8266 드라이버 c source code - smartconfig

이미지
 임베디드 리눅스 환경에서 esp8266 드라이버를 만드는 중이다.   ESP8266 모듈은 UART interface를 통해 연결하였으며, AT 커맨드를 사용하여 동작 명령 및 데이터를 주고받는다.  드라이버는 Linux user mode에서 동작하며, 현재는 smartconfig까지 구현되어 있다.  Smartconfig  Smartconfig는 esp8266이 station 모드에서 동작하며, wifi AP의 정보를 esp8266에 전달하여 ESP8266이 자동으로 wifi AP에 연결하도록 하는 기능이다.  wifi AP의 정보 전달은 wifi AP에 연결된 스마트 폰이나, 다른 디바이스로 전달할 수 있다. wifi AP의 정보 전달 app중 하나인 ESP-TOUCH는 google play에서 다운받을 수 있으며, 코드는 github(  https://github.com/EspressifApp/EsptouchForAndroid  )에서 다운받을 수 있다.   esp8266 모듈과는 다음과 같은 커맨드와 메세지를 주고받으며 smartconfig를 수행한다.  AT+CWMODE=1을 사용하여 Station모드로 변경하고, AT+CWSTARTSMART 커맨드를 사용하여 Smartconfig를 시작한다.  스마트폰의 app을 사용하여 wifi ap의 정보를 esp8266에 전달하면, esp8266d은 이 정보를 사용하여 wifi ap에 접속을 시도한다.  wifi ap에 접속하게 되면, WIFI CONNECTED, WIFI GOT IP등의 메시지를 리눅스 디바이스 쪽으로 보내온다.   Smartconfig를 성공하면, esp8266은 's...

linux uart 커널 설정 및 non-blocking 모드 시리얼 통신 example c code

이미지
 본 포스트는 uart 드라이버의 linux 커널 설정 방법과 linux user mode에서 동작하는 uart 통신 예제를 싣고 있다. 1. Kernel configuration uart serial 드라이버는 보통 사용할 수 있도록 설정되어 있다. 만약 확인이 필요하다면, 아래 리눅스 커널 menuconfig 이미지와 같이 Device Drivers의 Character devices가 활성화되어 있는지, Character devices내의 Serial drivers 내의 uart controller가 제대로 선택되었는지 보면 된다.  uart 세부 설정을 변경하고 싶으면, linux 커널의 dts(device tree script)파일이나 칩 제조사가 제공하는 설정 방법으로 변경할 수 있다. 아래 이미지는 allwinner사의 sys_config.fex파일에서의 설정 예이다. 아래 이미지는 dtsi 파일에의 uart 설정 예이다. dtsi파일은 arm 계열의 경우 /linux/arch/arm/boot/dts 폴더에 있다.  2. uart example code 2.1. uart 드라이버 설정 및 read/write 함수 아래 예제 코드는 non-blocking 방식으로 동작하도록 설정되어 있다. select 문을 사용해 수신된 데이터가 있는지 체크하도록 했다.  #ifndef __uart_h__ #define __uart_h__ #ifdef __cplusplus extern "C"{ #endif         int uart_open(char *dev, int baud_rate);         void uart_close(int uartd);         int u...

ATmega328PB i2c master mode example source

ATmega328PB에서 마스터 모드로 동작하는 i2c 예제 소스다. i2c led 컨트롤용으로 만들었던 코드다. 급하게 만들어서 read 함수가 없다. 컨트롤용이라 write만... datasheet를 보고 만들었다. 지금은 보드가 없어 read 함수 구현 테스트가 힘들다. 보드 생기면 구현해서 업데이트하자. iic.h #ifndef IIC_H_ #define IIC_H_ void iic_init(int ch); int write_iic(int ch, int address, int *data, int len); #endif /* IIC_H_ */ iic.c #define F_CPU 8000000UL // //#define F_CPU 16000000UL // #include <math.h> #include <stdlib.h> #include <inttypes.h> #include <avr/io.h> #include <avr/interrupt.h> #include <util/twi.h> #include <util/delay.h> #include "iic.h"   #ifndef TWI_FREQ #define TWI_FREQ 100000L #endif #define iic_timeout_ms 100 void iic_init(int ch) { if(ch == 0) { TWSR0 &= ~(1<<TWPS0); TWSR0 &= ~(1<<TWPS1); TWBR0 = ((F_CPU / ...

FT232H eeprom programming 시리얼 넘버 변경 예제

이미지
이번 글은 ft232h의 eeprom에 저장된 데이터 중 시리얼 넘버를 수정하는 예제 소스를 싣고 있다.   FT232H에는 EEPROM이 들어있고, 이 EEPROM에는 USB 장치의 속성 정보들이 저장되어 있다. 우리가 윈도우에서 장치 관리자를 통해 USB 장치의 속성을 볼 때 나오는 그런 정보들이 들어있으며, EEPROM에 들어있는 정보는 "ftd2xx.h" 헤더 파일에는 아래와 같이 선언되어 있다. // // structure to hold program data for FT_EE_Program, FT_EE_ProgramEx, FT_EE_Read  // and FT_EE_ReadEx functions // typedef struct ft_program_data { DWORD Signature1; // Header - must be 0x00000000  DWORD Signature2; // Header - must be 0xffffffff DWORD Version; // Header - FT_PROGRAM_DATA version // 0 = original // 1 = FT2232 extensions // 2 = FT232R extensions // 3 = FT2232H extensions // 4 = FT4232H extensions // 5 = FT232H extensions WORD VendorId; // 0x0403 WORD ProductId; // 0x6001 char *Manufacturer; // "FTDI" char *ManufacturerId; // "FT" char *Description; // "USB ...