목차 Input/Output Control I/O Control Mechanism mmap function munmap function RAM Area Access LED Control 4 digits 7 Segment Control Text LCD Control 1 2 I/O Control Mechanism (1) I/O Control Mechanism (2) Device Control Physical Address Control: application program Device Driver: kernel program 디바이스프로그램구현방법 커널의디바이스드라이버모듈등록 가상메모리접근에의한구현 사용자의응용프로그램특성에따라 device control 방식을선정 가상주소 (Virtual address) 실제존재하는물리주소가아니라, Linux kernel 내부에서일정한단계를거쳐논리적으로계산된다른주소체제 응용프로그램에서특정번지액세스 pointer 변수를이용하여해당 register 의 address 에원하는데이터를 write 하는 programming 예제 ) 물리주소 : 0xf100 0000, 데이터 : 0xc0 unsigned char *ptr; ptr = 0xf100 0000 /* register physical address */ *ptr = 0xc0 /* write data value to register */ 오류발생 : Linux kernel 에서물리적접근을허가하지않음, 가상주소를사용 3 4
mmap() 을이용한 I/O Control 가상주소액세스 : mmap() 메모리장치디바이스 /dev/mem : 시스템의 memory 공간에접근할수있는장치파일 응용프로그램에서특정 physical address 에접근 memory 장치디바이스를통한 lseek(), read(), write() 함수이용 memory 장치디바이스를통한 mmap() 함수이용 mmap 함수 열린파일기술자 (file descriptor) 를통해 access 되는파일의내용과관련된 memory 의구역에대한 pointer 를생성 file 이나 device driver 메모리에 mapping 시키는함수 응용프로그램코드에서 memory mapping 을구현하는방법은 mmap( ) 함수호출 mmap() 함수는파라메터 (argument) 에서제공된특정대상메모리에 mapping 한후에 mapping 된지점에해당되는가상주소를반환하는함수 mmap() 이호출되면, 프로그램제어권이 Linux kernel 로이관,Linuxkernel 은내부적으로 mmap() 함수인자를해석하여 mapping 영역을설정하고그위치에해당하는가상주소를계산하여 mmap() 으로반환 반환된가상주소에 pointer 변수에대입 5 6 mmap() function (1) mmap() function (2) mmap 함수의원형 void *mmap (void *start, size_t length, int prot, int flags, int fd, off_t offset); Arguments start: 특정 memory address 를요청하기위해, 일반적으로 0 으로설정 length: memory segment 의길이설정 port: memory segment 를위한액세스허용권한설정 flags: page 에가해지는변경이다른곳에반영되는방법설정 fd: 파일기술자 offset: 파일데이터의시작을변경 mapping 대상의시작위치를제시하며, mapping 대상의내용가운데이지점부터 memory 를 mapping Protection mode - PROT_EXEC: page execution - PROT_READ: page read 허락 - PROT_WRITE: page write 허락 - PROT_NONE: page access 불가 Flag parameters - MAP_FIXED: 특정한 mapping 위치로고정 - MAP_SHARED: 다른프로세스와 mapping 영역의공유가가능 - MAP_PRIVATE: mapping 을설정한자신만의 mapping 영역의사용이가능 7 8
Example of mmap() munmap() function Program example fd = open( /dev/mem,o_rdwr); addr = mmap(null,1,prot_write,map_shared,fd,addressofled); *addr = 0xaa; munmap(addr,1); close(fd) Header files #include <unistd.h> #include <sys/mman.h> #ifdef _POSIX_MAPPED_FILES start argument mapping 영역이시작되길원하는위치를의미하며, 통산 null 혹은 0 값으로대입을권고 0 값이아닌경우 flag 인자가 MAP_FIXED 일때 mapping 영역의시작위치가이값이되도록커널에서강제적으로요청할경우에사용 일반적으로 mapping 의시작위치는자동적으로비어있는영역을커널로선택하도록하는것이안전하므로 null 혹은 0 값으로대입 mmap 함수와함께쓰며, mmap 으로메핑된메모리를반환 mumap 함수원형 int munmap (void *start, size_t length); mmap 함수를사용하는방법 open() 함수를사용하여열린 file descriptor 를획득한다. mmap() 함수를사용하여제어할 I/O 의 pointer 획득한다. pointer 에서값을읽거나원하는값을쓴다. munmap() 함수를사용하여 memory 공간해제한다. close() 함수를이용하여열린 descriptor 를반환한다. 9 10 munmap() usage(1) munmap() usage(2) munmap() mmap() 과 pair 함수 Memory mapping 을해제하는기능 형식 #include <unistd.h> #include <sys/mman.h> int munmap (void *start, size_t length); Argument Start: mmmap() 에서반환했던가상주소를대입함으로서, 해제할 mapping 영역을공지 Length: 해제할때영역의길이를 byte 단위로계산하여대입 munmap() Return value Success: return (0) Fail: return (-1) munmap() 실행에따른오류반환값 EBADF: fd 가유효한파일기술자가아니다. 즉 MAP_ANONYMOUS 가설정되어있지않다. EACCES: MAP_PRIVATE 가설정되었지만, fd 가읽을수있도록열려있지않다. 또는 MAP_SHARED 와 PROT_WRITE 가설정되었지만, fd 가쓸수있도록열려있지않다. EINVAL: start 나 length 나 offset 가적당하지않다. 즉너무크거나 PAGESIZE 경계로정렬되어있지않다. ETXTBUSY: MAP_DENYWRITE 가설정되었으나, fd 로지정된객체가쓰기위해열려있다. EAGAIN: 파일이잠겨있거나, 너무많은 memory 가잠겨있다. ENOMEN: 사용할수있는메모리가없다. 11 12
가상메모리접근절차 예제 0xff00 0000 부터 1,024 바이트크기에해당하는물리적주소영역을 mmap() 에의해메모리 mapping 을시도하며, 그때얻어진가상주소에의해간단한포인터연산을한후에 mapping 영역을해제 접근절차 mmap() 의인자로사용될 mapping 의대상선정 : fd( 장치디바이스혹은파일 ) 매핑대상 ( 디바이스 ) 에대한 open mmap() 호출 : 목적에맞는인자설정 메모리 mapping 이성공적으로완료되며, 해당할당 mapping 메모리의 pointer 를접근하여데이터를접근 원하는연산이종료되어더이상 mapping 영역이필요없는경우에는 munmap() 으로해제 #include <stdlib.h> #include <unistd.h> #include <sys/mman.h> #include <asm/fcntl.h> Example of mmap() (1) int main() int men_fd; unsigned long *men_add32, *ptr; if((mem_fd=open( /dev/mem, O_RDWR)) < 0) perrpr( mem open fail\n ); exit(2); mem_addr32=mmap(null, 1240, (PRO_READ PROT_WRITE), MAP_SHARED, mem_fd, 0xff00 0000); if((int men_add32 < 0) mem_addr32 = NULL; printf( mmap error\n ); return -1; 13 14 Example of mmap() (2) RAM Area Access Control wrtie_data () ptr=mem_addr32; ptr=ptr+68; *ptr=0x1000 0401; ptr++; *ptr=0xf100 8000; RAM Area SRAM 256Kbytes 16 bits, 1Mbytes Hardware signal: PXA255 Chip Selection (CS) ncs3 0x0c000 0000 Diagram release_function() mummap(mem_add32, 1024); return 0; 15 16
RAM Area Access Program (1) RAM(0x0c00 0000) 을액세스하는프로그램코딩 (readram) /dev/mem mmap(,,,,, 0x0c0000000) mumap() Boot loader 상에서 0x0c00 0000 번지의데이터확인 (read) 및 1234568 을 write read b32 0x0c000000 a write b32 0x0c000000 12345678 Linux booting 및 RAM access 프로그램수행 EMPOS # boot #./readsram sram_val: 12345678 RAM Area Access Program (2) 1. SRAM 하드웨어번지를정의 : (prgram name: readram) #define ADDRESSOFSRAM 0x0c00 0000 2. 가상번지를저장할변수를저장하고, open 함수로 fd 설정 unsigned long *addr_sram; fd=open( /dev/mem",o_rdwr O_SYNC)) 3. mmap 함수를이용하여 SRAM 영역의가상번지를획득 addr_sram = mmap(null,1,prot_read,map_shared,fd,addressofsram); 4. 얻은번지의내용을확인하는코드삽입 printf("sram_val:[%x]\n",*addr_sram); 5. Makefile을작성하여컴파일 CC = arm linux gcc readsram: readsram.c $(CC) $(CFLAGS) o $@ $^ clean:rm f readsram 6. 확인된내용이정확한가를 bootloader에서재확인 EMPOS # read b32 0x0c000000 a 7. 로더에서 SRAM 영역에값을넣은후다시한번확인 EMPOS # write b32 0x0c000000 12345678 ;; bootloader에서해당번지에데이터를입력 EMPOS # boot ;; linux booting #./readsram ;; linux에서해당번지의 RAM을접근 sram_val:12345678 17 18 LED Control (1) LED Control (2) 8 개 SMD 형태의 LED 로구성 : 8bit(1 byte) write 구조 특정번지 (0x1060 0000) 에서데이터 bit 를출력으로 LED 를 on/off 제어 fd=open( /dev/mem, O_RDRW O_SYNC) led_addr=mmap(null, 1, PROT_WRITE, MAP_SHARED, fd, 0x10600000) led_light. *led_addr =0xaa, delay-fector(). munmp(led_addr, 1); 회로 LED Register: 0x1060 0000, 8bits 19 20
7 segment Control (1) 7 segment Control (2) 4 개의 7segment LED 로구성된 write 구조 4 개의 7segment 는 8 개의출력 bit 로구성 32bit CPU 제어를위해 2 개의 7segment 단위 (16bits) 로제어 7segment LED 정보지속을위해 latch 구조 회로 7segment_low =0x1030 0000 BCD-to-7segment Decoder Activate signal: positive, negative Display: 0-1 figures Code 1: 0bc0 0000 2: ab0d e0g0 a f g b 7segment_low =0x1040 0000 e d c dp 21 22 7 segment LED Data: Cathode type 7segment Program (1) Cathode type: active High Table 7 세그먼트비트값 표시 데이터값 dp g f e d c b a 0 0 0 1 1 1 1 1 1 0x3f 1 0 0 0 0 0 1 1 0 0x06 2 0 1 0 1 1 0 1 1 0x5f 3 0 1 0 0 1 1 1 1 0x4f 4 0 1 1 0 0 1 1 0 0x66 5 0 1 1 0 1 1 0 1 0x6d 6 0 1 1 1 1 1 0 1 0x7d 7 0 0 1 0 0 1 1 1 0x27 8 0 1 1 1 1 1 1 1 0x7f 9 0 1 1 0 1 1 1 1 0x6f Program char GetSegcode(char x) switch(x).. Header file #define segment7_l 0x10300000 #define segment7_h 0x10400000 void Showsegment(unsigned int highvalue, unsigned int lowvalue) addr_lseg=mmap(null,4,prot_write, MAP_SHARED, fd, segment7_l); addr_hseg=mmap(null,4,prot_write,map_shared, fd, segment7_h); *addr_lseg = lowvalue; *addr_hseg = highvalue; munmap(addr_lseg, 4); munmap(addr_hseg,4); int sizeofword(char *word) char Getsegcode(char x) switch(x).. 23 24
7segment Program (2) int main() int k; unsigned int low = 0,high = 0; char data[5]; strcpy(data,"0000"); k = sizeofword(data); switch(k) case 1: low = Getsegcode(data[0]); break; case 2: low = Getsegcode(data[0]); low = (low<<8) Getsegcode(data[1]); break; case 3: high = Getsegcode(data[0]); low = Getsegcode(data[1]); low = (low<<8) Getsegcode(data[2]); break; case 4: high = Getsegcode(data[0]); high = (high<<8) Getsegcode(data[1]); low = Getsegcode(data[2]); low = (low<<8) Getsegcode(data[3]); break; default : break; showsegment(high, low); exit(0); 25