#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/io.h>
#include <linux/delay.h>
#define GPIO_BASE 0xE0200000 // GPIO의 기본 물리주소
#define DB_CONF (0xC00/4) // DB로 사용할 핀을 설정하기위한 레지스터 주소
#define DB_DAT (0xC04/4) // DB로 사용할 핀에 데이터를 넣기위한 레지스터 주소
#define CTRL_CONF (0xC20/4) // LCD 제어를 위한 핀을 설정하기위한 레지스터 주소
#define CTRL_DAT (0xC24/4) // LCD 제어를 위한 핀에 데이터를 넣기위한 레지스터 주소
#define RS 0 // RS로 사용할 핀의 인덱스
#define RW 1 // RW로사용할 핀의 인덱스
#define EN 3 // EN으로 사용할 핀의 인덱스
#define DB4 0 // LCD DB4핀에 연결될 핀의 인덱스
#define DB5 1 // LCD DB5핀에 연결될 핀의 인덱스
#define DB6 2 // LCD DB6핀에 연결될 핀의 인덱스
#define DB7 3 // LCD DB7핀에 연결될 핀의 인덱스
#define MD 20 // LCD 제어시 필요한 delay
static volatile u32 *gpio_base = 0x0;
static void gpio_data( int, int, int); // 레지스터에 데이터를 넘겨주는 함수
static void gpio_config( int, int, int); // 레지스터 출력설정을 위한 함수
void textlcd_set( int); // LCD 모듈에 명령어를 전달하기위한 함수
void textlcd_init( void); // LCD 모듈 초기화를 위한 함수
void textlcd_write( char); // LCD 모듈에 문자를 넘겨주는 함수
void output_message( char *); // 사용자로부터 출력할문자열을 넘겨받는 함수
void gpio_init( void); // 각 핀들의 초기설정을 위한 함수
/*
모듈이 커널에 적재될 때 수행되는 함수로 초기화 작업을 한다.
- 메모리 매핑과 기본적인 핀설정, lcd 초기화, 메시지출력 함수를 호출한다.
*/
int module_start( void)
{
printk( "TEXT LCD device driver on!\n");
gpio_base = (u32 *)ioremap( GPIO_BASE, PAGE_SIZE);
gpio_init();
textlcd_init();
output_message("I CAN DO\nEVERYTHING!");
return 0;
}
/*
모듈이 커널에서 제거될 때 수행되는 함수로 마무리 작업을 한다.
- 메모리 매핑 해제를 한다.
*/
void module_end( void)
{
if( gpio_base)
{
printk("upmapping address!\n");
iounmap( (void*)gpio_base);
}
printk("TEXT LCD devier driver off!\n");
}
/*
사용할 핀들의 초기설정(output)을 해주는 함수이다.
- 모든 핀들을 output으로 설정한다.
*/
void gpio_init( void)
{
gpio_config( CTRL_CONF, RS, 1);
gpio_config( CTRL_CONF, RW, 1);
gpio_config( CTRL_CONF, EN, 1);
gpio_config( DB_CONF, DB4, 1);
gpio_config( DB_CONF, DB5, 1);
gpio_config( DB_CONF, DB6, 1);
gpio_config( DB_CONF, DB7, 1);
}
/*
입력받은 메시지를 LCD에 출력하는 함수이다.
- 한 글자씩 LCD로 전송해서 출력이 되게한다.
*/
void output_message( char *msg)
{
int c = 0;
int flag = 0;
textlcd_set( 0x80);
for( c = 0 ; c < strlen(msg) ; c ++)
{
if( (msg[c] == '\n' || c == 16) && flag == 0)
{
textlcd_set( 0xC0);
flag = 1;
if( msg[c] == '\n')
continue;
}
textlcd_write( msg[c]);
}
}
/*
gpio의 data register 값을 설정해주는 함수이다.
- 넘겨받은 pin의 위치와 값을 설정해준다.
- data register는 핀 당 1bit의 크기를 가진다.
*/
static void gpio_data( int gpio, int bit, int value)
{
u32 data = 0x0;
data = gpio_base[gpio];
data &= ~(1 << bit);
data |= (value << bit);
gpio_base[gpio] = data;
}
/*
gpio의 config register 값을 설정해주는 함수이다.
- 넘겨받은 pin의 위치와 값을 설정해준다.
- config register는 핀 당 4bit의 크기를 가진다.
*/
static void gpio_config( int gpio, int bit, int value)
{
u32 data = 0x0;
data = gpio_base[gpio];
data &= (~(0xF << (bit * 4)));
data |= (value << (bit * 4));
gpio_base[gpio] = data;
}
/*
text lcd에 문자를 출력하는 함수이다.
- 인자 값으로받은 한 글자의 메시지를 출력한다.
- 8bit 값의 데이터를 전송할 때는 상위 4니블을 전송하고, 하위4 니블을 전송한다.
*/
void textlcd_write( char dat)
{
gpio_data(CTRL_DAT, RS, 1);
gpio_data(CTRL_DAT, RW, 0);
mdelay(MD);
gpio_data(CTRL_DAT, EN, 1);
mdelay(MD);
gpio_base[DB_DAT] = (dat >> 4) & 0x0f;
gpio_data(CTRL_DAT, EN, 0);
mdelay(MD);
gpio_data(CTRL_DAT, EN, 1);
mdelay(MD);
gpio_base[DB_DAT] = dat & 0x0f;
gpio_data(CTRL_DAT, EN, 0);
}
/*
text lcd의 초기화 작업을 하는 함수이다.
- 레퍼런스를 참조하여 초기화 작업을 수행한다.
- 4bit interface로 동작되게 설정한다.
*/
void textlcd_init( void)
{
int c = 0;
mdelay(MD);
for( c = 0 ; c < 3 ; c ++)
{
gpio_data( CTRL_DAT, RS, 0);
gpio_data( CTRL_DAT, RW, 0);
mdelay(MD);
gpio_data( CTRL_DAT, EN, 1);
mdelay(MD);
gpio_base[DB_DAT] = 0x3;
gpio_data( CTRL_DAT, EN, 0);
mdelay(MD);
}
mdelay(MD);
gpio_data( CTRL_DAT, EN, 1);
mdelay(MD);
gpio_base[DB_DAT] = 0x2;
gpio_data( CTRL_DAT, EN, 0);
mdelay(MD);
textlcd_set( 0x28);
textlcd_set( 0x08);
textlcd_set( 0x01);
textlcd_set( 0x06);
textlcd_set( 0x0F);
}
/*
text lcd에 명령을 전송하는 함수이다.
- 4bit의 interface 이기 때문에 8bit 명령을 넘겨 받으면 상위4 니블 전송 후,
- 하위4 니블을 마저 전송한다.
*/
void textlcd_set( int data)
{
gpio_data( CTRL_DAT, RS, 0);
gpio_data( CTRL_DAT, RW, 0);
mdelay(MD);
gpio_data( CTRL_DAT, EN, 1);
mdelay(MD);
gpio_base[DB_DAT] = (data >> 4) & 0x0f;
gpio_data( CTRL_DAT, EN, 0);
mdelay(MD);
gpio_data( CTRL_DAT, EN, 1);
mdelay(MD);
gpio_base[DB_DAT] = data & 0x0f;
gpio_data( CTRL_DAT, EN, 0);
mdelay(MD);
}
module_init( module_start);
module_exit( module_end);
MODULE_LICENSE("GPL");
'임베디드(embedded) > 모듈 디바이스 드라이버' 카테고리의 다른 글
HC-SR04(ultrasonic) 초음파 센서 디바이스 드라이버 (device driver) (0) | 2015.09.22 |
---|