Mobile & Embedded System Lab. Dept. of Computer Engineering Kyung Hee Univ.
TextLCD Device Control in Embedded Linux M3 모듈에장착되어있는 Tedxt LCD 장치를제어하는 App을개발 TextLCD는영문자와숫자일본어, 특수문자를표현하는데사용되는디바이스 HBE-SM5-S4210의 TextLCD는 16문자 *2라인을 Display 할수있으며, 이 TextLCD를제어하기위하여 FPGA 내부에 Controller가설계되어있다. 2
TextLCD Device Control in Embedded Linux TextLCD 모듈은 8bit 의 micro-processor 와 2 개의레지스터 (DR, IR) 로구성되어있다. LCD 화면 RS HD 44780 R/W E DB0-DB7 입출력버퍼 IR DR DR CG HD 44100
TextLCD Device Control in Embedded Linux IR(Instruction Register) CPU 로부터받은데이터를써넣기만할수있다. LCD 화면클리어, 커서시프트, 글자 ON/OFF 등의 LCD 제어와관련된명령정보만을저장한다. 표시데이터 RAM(D.D.RAM) 과문자생성 RAM(C.G.RAM) 표시를위한 Address 정보를저장한다. P.5~P.12 까지 instruction 에대해설명 DR(Data Register) D.D.RAM 혹은 C.G.RAM 에써넣을데이터를저장하거나, D.D.RAM 혹은 C.G.RAM 으로부터읽혀진데이터가일시적으로저장되는레지스터이다. 또, CPU 로부터 DR 에써넣은데이터는 LCD 의내부동작으로 D.D.RAM 혹은 C.G.RAM 에자동으로써넣어진다.
TextLCD Device Control in Embedded Linux BIT TextLCD Control Register(read/write) 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Reserved CLCD_RS CLCD_RW CLCD_E CLCD_D7 CLCD_D6 CLCD_D5 CLCD_D4 CLCD_D3 CLCD_D2 CLCD_D1 CLCD_D0 Reset x x x x x 0 0 0 0 0 0 0 0 0 0 0 Bits Name Description 0 CLCD_D0 CLCD Data Bit 0 1 CLCD_D1 CLCD Data Bit 1 2 CLCD_D2 CLCD Data Bit 2 3 CLCD_D3 CLCD Data Bit 3 4 CLCD_D4 CLCD Data Bit 4 5 CLCD_D5 CLCD Data Bit 5 6 CLCD_D6 CLCD Data Bit 6 7 CLCD_D7 CLCD Data Bit 7 8 CLCD_E CLCD Enable Bit (Active High) 9 CLCD_RW CLCD Read/Write Control Bit ( 1 read, 0 Write) 10 CLCD_RS CLCD Data Instruction Register Set
TextLCD Device Control in Embedded Linux TextLCD 모듈의제어명령표 기능 제어신호제어명령 (D0 ~ D7) 실행시간 RS R/W 7 6 5 4 3 2 1 0 Clear Display 0 0 0 0 0 0 0 0 0 1 1.64ms Return Home 0 0 0 0 0 0 0 0 1 0 40us Entry Mode Set 0 0 0 0 0 0 0 1 I/D S 40us Display on/off control Cursor or Display Shift 0 0 0 0 0 0 1 D C S 40us 0 0 0 0 0 1 S/C R/L 0 0 40us Function Set 0 0 0 0 1 D/L N F 0 0 40us Set CG RAM Address 0 0 0 1 CG RAM Address 40us Set DD RAM Address Read Busy Flag and Address Data Write to CG RAM or DD RAM Data Read to CG RAM or DD RAM 0 0 1 DD RAM Address 40us 0 1 BF Address Counter 40us 1 0 Write Address 40us 1 1 Read Address 40us
TextLCD Device Control in Embedded Linux D.D.RAM Address Set DR 의문자가표시될커서위치 DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 1 A6 A5 A4 A3 A2 A1 A0 열 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 행 1 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 행 2 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
TextLCD Device Control in Embedded Linux C.G.RAM Address Set DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 1 A5 A4 A3 A2 A1 A0
TextLCD Device Control in Embedded Linux Function Set DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 1 DL N F x x DL=1: 8 비트 (DB7~DB0) 인터페이스세트 DL=0: 4 비트 (DB7~DB4) 인터페이스세트상위 4 비트전송후하위 4 비트전송 N: 표시행수를설정 F: 문자폰트를설정 N F 표시행수 문자폰트 듀티비 0 0 1 5x7 도트 1/8 0 1 1 5x10 도트 1/11 1 x 2 5x7 도트 1/16
TextLCD Device Control in Embedded Linux Cursor/Display Shift DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 1 S/C R/L x x D.D.RAM 의내용은변경하지않고커서이동과표시쉬프트를한다. 커서의이동은 1 행의 40 번째에서 2 행의처음으로온다. 그러나표시쉬프트는두행이동시에수행된다. S/C R/L 동작 0 0 커서위치를좌로이동 (AC -= 1) 0 1 커서위치를우로이동 (AC += 1) 1 0 표시전체를좌로이동. 표시는커서에따라움직인다. 1 1 표시전체를우로이동. 커서는움직이지않는다.
TextLCD Device Control in Embedded Linux Display ON/OFF control DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 0 1 D C B 표시 ON/OFF, 커서 ON/OFF, 커서위치에있는문자의 blink ON/OFF 를설정한다. 비트 1 0 D 표시 ON 표시 OFF C 커서 ON 커서 OFF B 문자 blink ON 문자 blink OFF
TextLCD Device Control in Embedded Linux Entry mode DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 0 0 1 I/D S 커서의진행방향이나표시된문자를시프트시킬것인지를설정한다. I/D(Increment/Decrement): I/D = 1 (Address + 1 ) I/D = 0 (Address 1 ) S(Shift): S=1 일때표시된문자전체를좌 / 우로이동 ID=1, S=1 : 왼쪽으로 shift ID=0, S=1 : 오른쪽으로 shift S = 0 : 표시된문자는 shift 되지않는다.
TextLCD Device Control in Embedded Linux Cursor Home DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 0 0 0 1 x 커서를 LCD 맨처음으로돌아가게한다. 이때 AC 에 D.D.RAM 의 address 에 0 번지가 set 된다. x : 보통무효비트라고하며, 0 값이든 1 값이든상관없다.
TextLCD Device Control in Embedded Linux Display clear DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 0 0 0 0 1 화면클리어후커서는홈위치로돌아간다. 그리고 D.D.RAM 의모든어드레스에스페이스코드인 0x20 이들어가고 AC(Address Counter) 에 D.D.RAM 어드레스 0 번지가세트된다. AC 는 D.D./C.G.RAM 으로데이터를쓰거나기억된데이터를읽을때목적지가되는 RAM 의어드레스를지정한다. IR 에어드레스세트인스트럭션을써넣으면 IR 에서 AC 로어드레스정보가전송되는것이다.
TextLCD Device Driver Device Driver Version 소스파일작성 TextLcd 리눅스디바이스드라이버는커널에포함되어있다. menuconfig 실행 Device Drivers -> [*] Misc devices -> [*] Hanback Electronics M3(FPGA) Device Support -> <*>TEXT LCD root@ubuntu:~/working/linux-2.6.35-s4210# make menuconfig 15
TextLCD Device Driver 소스파일확인 소스코드는 ~/working/linux-2.6.35-s4210/drivers/misc/hanback 에있다. root@ubuntu:~/working/linux-2.6.35-s4210# cd drivers/misc/hanback root@ubuntu:~/working/linux-2.6.35-s4210# vi textlcd.c 001: #include <linux/init.h> 002: #include <linux/module.h> 003: #include <linux/kernel.h> 004: #include <linux/fs.h> 005: #include <linux/errno.h> 006: #include <linux/types.h> 007: #include <linux/ioport.h> 008: #include <asm/io.h> 009: #include <asm/ioctl.h> 010: #include <asm/uaccess.h> 011: #include <linux/delay.h> 012: #include <linux/miscdevice.h> 013: #include <linux/platform_device.h> 014: #include <linux/mm.h> 015: #include <asm/cacheflush.h> 016: #include "textlcd.h" 017: 16
TextLCD Device Driver 018: void setcommand(unsigned short command) 019: { 020: command &= 0x00FF; 022: *textlcd_ioremap = command 0x0000; 023: mdelay(1); 024: *textlcd_ioremap = command 0x0100; 025: mdelay(1); 026: *textlcd_ioremap = command 0x0000; 027: mdelay(1); 028: } 030: void writebyte(char ch) 031: { 032: unsigned short data; 033: data = ch & 0x00FF; 034: 035: *textlcd_ioremap = data & 0x400; 036: mdelay(1); 037: *textlcd_ioremap = data 0x500; 038: mdelay(1); 039: *textlcd_ioremap = data 0x400; 040: mdelay(1); 041: } 17
TextLCD Device Driver 043: void initialize_textlcd() 044: { 045: function_set(2,0); //Function Set:8bit,display 2lines,5x7mode 046: display_control(1,0,0); // Display on, Cursor off 047: clear_display(); // Display clear 048: entry_mode_set(1,0); // Entry Mode Set : shift right cursor 049: return_home(); // go home 050: } 051: 052: int function_set(int rows, int nfonts) 053: { 054: unsigned short command = 0x30; 055: 056: if(rows == 2) command = 0x08; 057: else if(rows == 1) command &= 0xf7; 058: else return -1; 059: 060: command = nfonts? (command 0x04) : command; 061: setcommand(command); 062: return 1; 063: } 18
TextLCD Device Driver 065: int display_control(int display_enable, int cursor_enable, int n blink) 066: { 067: unsigned short command = 0x08; 068: command = display_enable? (command 0x04) : command; 069: command = cursor_enable? (command 0x02) : command; 070: command = nblink? (command 0x01) : command; 071: setcommand(command); 072: return 1; 073: } 074: 075: int cursor_shift(int set_screen, int set_rightshit) 076: { 077: unsigned short command = 0x10; 078: command = set_screen? (command 0x08) : command; 079: command = set_rightshit? (command 0x04) : command; 080: setcommand(command); 081: return 1; 082: } 19
TextLCD Device Driver 084: int entry_mode_set(int increase, int nshift) 085: { 086: unsigned short command = 0x04; 087: command = increase? (command 0x2) : command; 088: command = nshift? ( command 0x1) : command; 089: setcommand(command); 090: return 1; 091: } 092: 093: int return_home() 094: { 095: unsigned short command = 0x02; 096: setcommand(command); 097: return 1; 098: } 099: 100: int clear_display() 101: { 102: unsigned short command = 0x01; 103: setcommand(command); 104: return 1; 105: } 20
TextLCD Device Driver 107: int set_ddram_address(int pos) 108: { 109: unsigned short command = 0x80; 110: command += pos; 111: setcommand(command); 112: return 1; 113: } 115: static int textlcd_open(struct inode *minode, struct file *mfile ) 116: { 117: if(textlcd_usage!= 0) return -EBUSY; 118: 119: textlcd_ioremap= (unsigned short *)ioremap(textlcd_address,tex TLCD_ADDRESS_RANGE); 120: 121: if(!check_mem_region((unsigned long)textlcd_ioremap,textlcd_a DDRESS_RANGE)) 122: { 123: request_mem_region((unsigned long)textlcd_ioremap,textlcd _ADDRESS_RANGE,TEXTLCD_NAME); 124: } 21
TextLCD Device Driver 125: else printk(kern_warning"can't get IO Region 0x%x\n",TEXTLC D_ADDRESS); 126: 127: textlcd_usage = 1; 128: initialize_textlcd(); 129: return 0; 130: } 131: 132: static int textlcd_release(struct inode *minode, struct file *mf ile) 133: { 134: iounmap(textlcd_ioremap); 135: 136: release_mem_region((unsigned long)textlcd_ioremap,textlcd_a DDRESS_RANGE); 137: 138: textlcd_usage = 0; 139: return 0; 140: } 22
TextLCD Device Driver 142: static ssize_t textlcd_write(struct file *inode, const char*gdat a, size_t length, loff_t *off_what) 143: { 144: int i,ret; 145: char buf[100]; 146: 147: ret=copy_from_user(buf,gdata,length); 148: 149: if(ret < 0) return -1; 150: 151: for(i=0;i<length;i++) { 152: writebyte(buf[i]); 153: } 154: return length; 155: } 156: 157: static int textlcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long gdata) 158: { 159: struct strcommand_varible strcommand; 160: int ret; 23
TextLCD Device Driver 161: 162: ret=copy_from_user(&strcommand,(char *)gdata,32); 163: if(ret<0) return -1; 164: 165: switch(cmd){ 166: case TEXTLCD_COMMAND_SET: 167: setcommand(strcommand.command); 168: break; 169: case TEXTLCD_FUNCTION_SET: 170: function_set((int)(strcommand.rows+1),(int)(strcommand. nfonts)); 171: break; 172: case TEXTLCD_DISPLAY_CONTROL: 173: display_control((int)strcommand.display_enable, 174: (int)strcommand.cursor_enable,(int)strcommand.nblink); 175: break; 176: case TEXTLCD_CURSOR_SHIFT: 177: cursor_shift((int)strcommand.set_screen,(int)strcommand.set_rightshit); 178: break; 24
TextLCD Device Driver 179: case TEXTLCD_ENTRY_MODE_SET: 180: entry_mode_set((int)strcommand.increase,(int)strc ommand.nshift); 181: break; 182: case TEXTLCD_RETURN_HOME: 183: return_home(); 184: break; 185: case TEXTLCD_CLEAR: 186: clear_display(); 187: break; 188: case TEXTLCD_DD_ADDRESS: 189: set_ddram_address((int)strcommand.pos); 190: break; 191: case TEXTLCD_WRITE_BYTE: 192: writebyte(strcommand.buf[0]); 193: break; 194: default: 195: printk("driver : no such command!\n"); 196: return -ENOTTY; 197: } 198: return 0; 199: } 25
TextLCD Device Driver 201: static struct file_operations textlcd_fops = { 202:.owner = THIS_MODULE, 203:.open = textlcd_open, 204:.write = textlcd_write, 205:.ioctl = textlcd_ioctl, 206:.release = textlcd_release, 207: }; 208: 209: static struct miscdevice text_driver = { 210:.fops = &textlcd_fops, 211:.name = TEXTLCD_NAME, 212:.minor = MISC_DYNAMIC_MINOR, 213: }; 214: 215: int textlcd_init(void) 216: { 217: misc_register(&text_driver); 218: return 0; 219: } 26
TextLCD Device Driver 221: void textlcd_exit(void) 222: { 223: misc_deregister(&text_driver); 224: printk("driver: %s DRIVER EXIT\n", TEXTLCD_NAME); 225: } 226: 227: module_init(textlcd_init); 228: module_exit(textlcd_exit); 229: 230: MODULE_AUTHOR(DRIVER_AUTHOR); 231: MODULE_DESCRIPTION(DRIVER_DESC); 232: MODULE_LICENSE("Dual BSD/GPL"); 27
TextLCD Application Program 테스트프로그램작성 소스코드는 [CD3]/source/application_peri/device_driver/textlcd_driver에있다. ( 밑에작성하는 Makefile도동일한위치에있다.) root@ubuntu:~/working/device_driver/textlcd_driver# vi textlcd_test.c 001: #include <stdio.h> 002: #include <stdlib.h> 003: #include <string.h> 004: #include <unistd.h> 005: #include <sys/types.h> 006: #include <sys/stat.h> 007: #include <fcntl.h> 008: #include <sys/ioctl.h> 009: 010: #define TEXTLCD_BASE 0xbc 011: #define TEXTLCD_COMMAND_SET _IOW(TEXTLCD_BASE,0,int) 012: #define TEXTLCD_FUNCTION_SET _IOW(TEXTLCD_BASE,1,int) 28
TextLCD Application Program 013: #define TEXTLCD_DISPLAY_CONTROL _IOW(TEXTLCD_BASE,2,int) 014: #define TEXTLCD_CURSOR_SHIFT _IOW(TEXTLCD_BASE,3,int) 015: #define TEXTLCD_ENTRY_MODE_SET _IOW(TEXTLCD_BASE,4,int) 016: #define TEXTLCD_RETURN_HOME _IOW(TEXTLCD_BASE,5,int) 017: #define TEXTLCD_CLEAR _IOW(TEXTLCD_BASE,6,int) 018: #define TEXTLCD_DD_ADDRESS _IOW(TEXTLCD_BASE,7,int) 019: #define TEXTLCD_WRITE_BYTE _IOW(TEXTLCD_BASE,8,int) 020: 021: struct strcommand_varible { 022: char rows; 023: char nfonts; 024: char display_enable; 025: char cursor_enable; 026: char nblink; 027: char set_screen; 028: char set_rightshit; 029: char increase; 030: char nshift; 031: char pos; 032: char command; 033: char strlength; 034: char buf[16]; 035: }; 29
TextLCD Application Program 037: int main(int argc, char **argv) 038: { 039: int i,dev; 040: char buf0[16] = "Welcome to the "; 041: char buf1[16] = "Embedded World!!"; 042: char buf2[16] = " HANBACK "; 043: char buf3[16] = " Electronics "; 044: 045: struct strcommand_varible strcommand; 046: strcommand.rows = 0; 047: strcommand.nfonts = 0; 048: strcommand.display_enable = 1; 049: strcommand.cursor_enable = 0; 050: strcommand.nblink = 0; 051: strcommand.set_screen = 0; 052: strcommand.set_rightshit = 1; 053: strcommand.increase = 1; 054: strcommand.nshift = 0; 055: strcommand.pos = 10; 056: strcommand.command = 1; 057: strcommand.strlength = 16; 30
TextLCD Application Program 059: dev = open("/dev/textlcd", O_WRONLY O_NDELAY ); 060: 061: if (dev!= -1) { 062: write(dev,buf0,16); 063: strcommand.pos = 40; 064: ioctl(dev,textlcd_dd_address,&strcommand,32); 065: write(dev,buf1,16); 066: sleep(1); 067: 068: ioctl(dev,textlcd_clear,&strcommand,32); 069: 070: strcommand.pos = 0; 071: ioctl(dev,textlcd_dd_address,&strcommand,32); 072: for(i=0;i<16;i++) { 073: strcommand.buf[0]=buf2[i]; 074: ioctl(dev,textlcd_write_byte,&strcommand,32); 075: } 31
TextLCD Application Program 076: 077: strcommand.pos = 40; 078: ioctl(dev,textlcd_dd_address,&strcommand,32); 079: for(i=0;i<16;i++) { 080: strcommand.buf[0]=buf3[i]; 081: ioctl(dev,textlcd_write_byte,&strcommand,32); 082: } 083: 084: if(argc>=2) { 085: sleep(1); 086: ioctl(dev,textlcd_clear,&strcommand,32); 087: write(dev,argv[1],strlen(argv[1])); 088: if(argc==3) { 089: strcommand.pos = 40; 090: ioctl(dev,textlcd_dd_address,&strcomman d,32); 091: write(dev,argv[2],strlen(argv[2])); 092: } 093: } 094: 095: close(dev); 32
TextLCD Application Program 096: } else { 097: printf( "application : Device Open ERROR!\n"); 098: exit(1); 099: } 100: return 0; 101: } 33
TextLCD Application Program root@ubuntu:~/working/device_driver/textlcd_driver# vi Makefile CC = arm-linux-gcc CFLAGS = -DNO_DEBUG EXEC=textlcd_test OBJS=$(EXEC).o ####### Implicit rules.suffixes:.cpp.cxx.cc.c.c.cpp.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.cxx.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.cc.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.C.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.c.o: $(CC) -c $(CFLAGS) -o $@ $< all: $(EXEC) $(EXEC): $(OBJS) $(CC) -o $@ $^ clean: rm -f $(OBJS) $(EXEC) 34
TextLCD Application Program 컴파일 root@ubuntu:~/working/device_driver/textlcd_driver# ls Makefile textlcd_test.c root@ubuntu:~/working/device_driver/textlcd_driver# make clean;make ------------------ 다음과같은메시지가출력된다 ----------------- rm f textlcd_test.o textlcd_test arm-linux-gcc c DNO_DEBUG o textlcd_test.o textlcd_test.c arm-linux-gcc o textlcd_test textlcd_test.o root@ubuntu:~/working/device_driver/textlcd_driver# ls Makefile textlcd_test textlcd_test.c textlcd_test.o 타겟보드에다운받기및실행 타겟보드에서 tftp 로다운받기위해 textlcd_test 파일을 /var/lib/tftpboot 에복사 root@ubuntu:~/working/device_driver/textlcd_driver# cp tex tlcd _test /var/lib/tftpboot 35
TextLCD Application Program /var/lib/tftpboot로복사가완료되면타겟보드에서아래와같이명령어를입력 textlcd_test를다운받고 chmod 명령어를사용하여실행권한부여 [root@sm5s4210 ~]$ cd /root/device_driver [root@sm5s4210 device_driver]$ tftp -r textlcd_test -g 192.1 68.0.100 [root@sm5s4210 device_driver]$ ll -rw-r--r-- 1 root root 7250 Sep 1 5 17:19 textlcd_test [root@sm5s4210 device_driver]$ chmod +x textlcd_test [root@sm5s4210 device_driver]$ ll -rwxr-xr-x 1 root root 7250 Sep 1 5 17:19 textlcd_test 36
TextLCD Application Program (mmap) mmap Version ~/working/mmap/textlcd 디렉터리에서 textlcd.c 작성 소스코드는 [CD3]/source/application_peri/mmap/textlcd에있다. ( 밑에작성하는 Makefile도동일한위치에있다.) root@ubuntu:# mkdir -p ~/working/mmap/textlcd root@ubuntu:# cd ~/working/mmap/textlcd/ root@ubuntu:~/working/mmap/textlcd# vi textlcd.c 001: #include <stdio.h> 002: #include <string.h> 003: #include <stdlib.h> 004: #include <unistd.h> 005: #include <sys/mman.h> 006: #include <fcntl.h> 007: 008: #define FPGA_BASEADDRESS 0x05000000 009: #define TEXTLCD_OFFSET 0x10 010: 011: void setcommand(unsigned short command); 012: void writebyte(char ch); 013: void initialize_textlcd(); 014: int function_set(int rows, int nfonts); 37
TextLCD Application Program (mmap) 015: int display_control(int display_enable, int cursor_enable, int nblink); 016: int cursor_shift(int set_screen, int set_rightshit); 017: int entry_mode_set(int increase, int nshift); 018: int return_home(); 019: int clear_display(); 020: int set_ddram_address(int pos); 021: 022: unsigned short *addr_fpga, *ptextlcd; 023: 024: int main(int argc, char **argv) 025: { 026: int fd; 027: int i, len1=17,len2=17; 028: char buf1[17] = "Welcome to the "; 029: char buf2[17] = "Embedded World!!"; 030: 031: if ((fd=open("/dev/mem", O_RDWR O_SYNC)) < 0) { 032: printf("mem open fail\n"); 033: exit(1); 034: } 38
TextLCD Application Program (mmap) 035: 036: addr_fpga= (unsigned short *)mmap(null, 4096, PROT_READ PROT_WRITE, MAP_SHARED, fd, FPGA_BASEADDRESS); 037: ptextlcd = addr_fpga + TEXTLCD_OFFSET/sizeof(unsigned short); 038: 039: if(*ptextlcd == (unsigned short)-1) { 040: close(fd); 041: printf("mmap error\n"); 042: exit(1); 043: } 044: 045: if(argc == 2) { 046: len1 = strlen(argv[1]); 047: len2 = 0; 048: strcpy(buf1,argv[1]); 049: }else if(argc >= 3) { 050: len1 = strlen(argv[1]); 051: len2 = strlen(argv[2]); 052: strcpy(buf1,argv[1]); 053: strcpy(buf2,argv[2]); 054: } 39
TextLCD Application Program (mmap) 056: initialize_textlcd(); 057: 058: for(i=0;i<len1;i++) writebyte(buf1[i]); 059: set_ddram_address(0x40); 060: for(i=0;i<len2;i++) writebyte(buf2[i]); 061: 062: printf("- Textlcd\n"); 063: printf("line 1 : "); 064: for(i=0;i<len1;i++) printf("%c", buf1[i]); 065: printf("\nline 2 : "); 066: for(i=0;i<len2;i++) printf("%c", buf2[i]); 067: printf("\n"); 068: 069: munmap(ptextlcd,4096); 070: close(fd); 071: return 0; 072: } 40
TextLCD Application Program (mmap) 074: void setcommand(unsigned short command) 075: { 076: command &= 0x00FF; 077: *ptextlcd = command 0x0000; 078: usleep(1000); 079: *ptextlcd = command 0x0100; 080: usleep(1000); 081: *ptextlcd = command 0x0000; 082: usleep(1000); 083: } 41
TextLCD Application Program (mmap) 085: void writebyte(char ch) 086: { 087: unsigned short data; 088: data = ch & 0x00FF; 089: *ptextlcd = data&0x400; 090: usleep(1000); 091: *ptextlcd = data 0x500; 092: usleep(1000); 093: *ptextlcd = data 0x400; 094: usleep(1000); 095: 096: } 42
TextLCD Application Program (mmap) 098: void initialize_textlcd() { 099: function_set(2,0); 100: display_control(1,0,0); 101: clear_display(); 102: entry_mode_set(1,0); 103: return_home(); 104: } 105: 106: int function_set(int rows, int nfonts) { 107: unsigned short command = 0x30; 108: 109: if(rows == 2) command = 0x08; 110: else if(rows == 1) command &= 0xf7; 111: else return -1; 112: 113: command = nfonts? (command 0x04) : command; 114: setcommand(command); 115: return 1; 116: } 43
TextLCD Application Program (mmap) 118: int display_control(int display_enable, int cursor_enable, int nblink) { 119: unsigned short command = 0x08; 120: command = display_enable? (command 0x04) : command; 121: command = cursor_enable? (command 0x02) : command; 122: command = nblink? (command 0x01) : command; 123: setcommand(command); 124: return 1; 125: } 126: 127: int cursor_shift(int set_screen, int set_rightshit) { 128: unsigned short command = 0x10; 129: command = set_screen? (command 0x08) : command; 130: command = set_rightshit? (command 0x04) : command; 131: setcommand(command); 132: return 1; 133: } 44
TextLCD Application Program (mmap) 135: int entry_mode_set(int increase, int nshift) { 136: unsigned short command = 0x04; 137: command = increase? (command 0x2) : command; 138: command = nshift? ( command 0x1) : command; 139: setcommand(command); 140: return 1; 141: } 142: 143: int return_home() { 144: unsigned short command = 0x02; 145: setcommand(command); 146: return 1; 147: } 148: 149: int clear_display() { 150: unsigned short command = 0x01; 151: setcommand(command); 152: return 1; 153: } 45
TextLCD Application Program (mmap) 155: int set_ddram_address(int pos) { 156: unsigned short command = 0x80; 157: command += pos; 158: setcommand(command); 159: return 1; 160: } 46
TextLCD Application Program (mmap) 소스를컴파일하기위한 Makefile 을작성 root@ubuntu:~/working/mmap/textlcd# vi Makefile CC = arm-linux-gcc CFLAGS = -DNO_DEBUG EXEC=textlcd OBJS=$(EXEC).o ####### Implicit rules.suffixes:.cpp.cxx.cc.c.c.cpp.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.cxx.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.cc.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.C.o: $(CXX) -c $(CXXFLAGS) -o $@ $<.c.o: $(CC) -c $(CFLAGS) -o $@ $< all: $(EXEC) $(EXEC): $(OBJS) $(CC) -o $@ $^ clean: rm -f $(OBJS) $(EXEC) 47
TextLCD Application Program (mmap) make 명령어를실행하여소스를컴파일하고, 실행파일 (textlcd) 를 /var/lib/tftpboot 에복사 root@ubuntu:~/working/mmap/textlcd# make arm-linux-gcc -c -DNO_DEBUG -o textlcd.o textlcd.c arm-linux-gcc -o textlcd textlcd.o root@ubuntu:~/working/mmap/textlcd# ls Makefile textlcd textlcd.c textlcd.o root@ubuntu:~/working/mmap/textlcd# cp textlcd /var/lib/tftpboot/ 타겟보드에서실행파일 (textlcd) 를다운받고, 권한을변경한후실행 [root@sm5s4210 ~]$ tftp -r textlcd -g 192.168.0.100 [root@sm5s4210 ~]$ ls -l -rw-r--r-- 1 root root 9365 Aug 1 11:46 textlcd [root@sm5s4210 ~]$ chmod 777 textlcd [root@sm5s4210 ~]$./textlcd - Textlcd LINE 1 : Welcome to the LINE 2 : Embedded World!! [root@sm5s4210 ~]$./textlcd HBE-SM5-S4210 hanback.co.kr - Textlcd LINE 1 : HBE-SM5-S4210 LINE 2 : hanback.co.kr 48