도와주세요!!
글 수 15,339
2006.09.25 13:41:38 (*.188.43.136)
157164
/*-----------------------------------------------------------------------------
파 일 : s3c2410_timer.c
설 명 : S3C2410 의 타이머 0 을 사용하여 등록된 함수를 주기적으로 호출한다
작 성 : 오재경 freefrug@falinux.com
날 짜 : 2005-12-19
수 정 : 장형기 tsheaven@falinux.com
날 짜 : 2007-07-29
주 의 :
-------------------------------------------------------------------------------*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <asm/hardware.h>
#include <asm/arch/regs-timer.h>
#include <asm/arch/regs-irq.h>
#include <asm/arch/regs-gpio.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/ioctl.h>
#include <asm/unistd.h>
#include <asm/io.h>
#include "dev_gpio.h"
#include "s3c2410_timer.h"
#define PCLK 66500000
#define TICKS_PER_SECOND (PCLK/(255+1)/8) //
#define ONE_SEC_CLK (0xFFFF) // 65535 ( TCNTBn ) - Maximuim interval
#define ONE_MSEC_CLK (ONE_SEC_CLK/1000)
#define ONE_100USEC_CLK ((ONE_SEC_CLK/10000)+1)
#define USE_TICK_PERIOD ONE_100USEC_CLK
#define CALCU_TICK_FOR_USEC(x) ( (x) / 100 )
#define TIMER_A_IRQ IRQ_TIMER1
#define MAX_REQUEST 32
#define TIMER_USEC_SHIFT 16
#define DEV_NAME "dev-gpio"
#define DEV_VERSION DEV_NAME" V01"
// 타이머 큐 정보 구조체
typedef struct _mcutm_hdl {
int tick; // 시간계산 카운트
void *data; // 함수호출 인자
void (*routin)( void *); // 인터럽트에서 호출할 함수
struct _mcutm_hdl *next; // 현재 사용하지 않는다
} mcutm_hdl_t;
/*----------------------------------------------------------------------------*/
static mcutm_hdl_t *mcutm_list;
static int reqcnt = 0;
static int showmsg = 0;
static int major = DEV_MAJOR_DEF;
/* implementaion =============================================================*/
#define reg_s2410(x) *(volatile unsigned long *)(x)
#define set_GPIO_IN(reg, nr) reg &= ~(3<<(nr)*2)
#define set_GPIO_OUT(reg, nr) reg &= ~(3<<(nr)*2); reg |= (1<<(nr)*2)
#define GPIO_IN(reg,nr) (reg & (1<<(nr)) ? 1:0)
#define GPIO_OUT(reg,nr,val) reg &= ~(1<<(nr)); reg |= (val&0x1)<<(nr);
/*-----------------------------------------------------------------------------
설 명 : 타이머를 설정한다.
주 의 :
-------------------------------------------------------------------------------*/
static void mcutm_reload( unsigned long tick )
{
unsigned long tcon;
// timer stop
tcon = __raw_readl(S3C2410_TCON);
tcon &= ~(0xF<<8); // Timer 1 = 8
__raw_writel(tcon, S3C2410_TCON);
// Timer 0 Count Buffer Register
__raw_writel(tick, S3C2410_TCMPB(1));
__raw_writel(tick, S3C2410_TCNTB(1));
/* start the timer running */
tcon |= S3C2410_TCON_T1MANUALUPD;
__raw_writel(tcon, S3C2410_TCON);
tcon &= ~(0xF<<8);
tcon |= S3C2410_TCON_T1START;
__raw_writel(tcon, S3C2410_TCON);
}
/*-----------------------------------------------------------------------------
설 명 : GPIO 입출력을 설정한다.
주 의 :
-------------------------------------------------------------------------------*/
void hw_gp_init( void )
{
//F
set_GPIO_IN( reg_s2410(S3C2410_GPFCON), 4 );
set_GPIO_IN( reg_s2410(S3C2410_GPFCON), 5 );
set_GPIO_OUT( reg_s2410(S3C2410_GPFCON), 6 );
set_GPIO_OUT( reg_s2410(S3C2410_GPFCON), 7 );
//B
set_GPIO_OUT(reg_s2410(S3C2410_GPBCON),0);
set_GPIO_OUT(reg_s2410(S3C2410_GPBCON),1);
set_GPIO_OUT(reg_s2410(S3C2410_GPBCON),2);
set_GPIO_OUT(reg_s2410(S3C2410_GPBCON),3);
set_GPIO_OUT(reg_s2410(S3C2410_GPBCON),4);
// 내부 pull-up disable 7..4
reg_s2410(S3C2410_GPFUP) |= 0x00;
reg_s2410(S3C2410_GPBUP) |= 0x00;
// F off
GPIO_OUT( reg_s2410(S3C2410_GPFDAT), 6, 1 );
GPIO_OUT( reg_s2410(S3C2410_GPFDAT), 7, 1 );
// B off
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), 0, 1 );
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), 1, 1 );
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), 2, 1 );
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), 3, 1 );
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), 4, 1 );
}
/*-----------------------------------------------------------------------------
설 명 : GPIO 출력
주 의 :
-------------------------------------------------------------------------------*/
void hw_gpf_out(int gpnr, int val )
{
GPIO_OUT( reg_s2410(S3C2410_GPFDAT), gpnr, val );
}
void hw_gpb_out(int gpnr, int val)
{
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), gpnr, val );
}
/*-----------------------------------------------------------------------------
설 명 : GPIO 입력
주 의 :
-------------------------------------------------------------------------------*/
int hw_gpf_in(int gpnr )
{
return GPIO_IN( reg_s2410(S3C2410_GPFCON), gpnr);
}
int hw_gpb_in(int gpnr )
{
return GPIO_IN( reg_s2410(S3C2410_GPBCON), gpnr);
}
static irqreturn_t mcutm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
mcutm_hdl_t *hdl = mcutm_list;
int loop, mach;
unsigned long tcon;
// Timer 정지
tcon = __raw_readl(S3C2410_TCON);
tcon &= ~(S3C2410_TCON_T1START) | ~(S3C2410_TCON_T1RELOAD);
__raw_writel(tcon, S3C2410_TCON);
mach = reqcnt;
for (loop=0; loop<MAX_REQUEST; loop++ )
{
if ( hdl->tick > 0 )
{
hdl->tick --;
if ( 0 == hdl->tick )
{
if ( hdl->routin ) hdl->routin( hdl->data );
reqcnt --;
}
mach --;
if ( mach <= 0 ) break;
}
hdl ++;
}
if ( 0 < reqcnt )
{
mcutm_reload( USE_TICK_PERIOD );
}
return IRQ_HANDLED;
}
/*-----------------------------------------------------------------------------
설 명 : 핸들러를 등록한다.
주 의 :
-------------------------------------------------------------------------------*/
int gpio_release( struct inode *inode, struct file *filp)
{
module_put(THIS_MODULE);
if (showmsg) printk(" %s CLOSEn", DEV_NAME );
return 0;
}
int mcutm_requset( unsigned int index, int usec, void (*routin)( void *), void *data )
{
mcutm_hdl_t *hdl;
unsigned long flags;
if ( MAX_REQUEST <= index ) return -1;
if ( usec <= 0 ) return -1;
hdl = mcutm_list + index;
hdl->tick = CALCU_TICK_FOR_USEC(usec);
hdl->data = data;
hdl->routin = routin;
hdl->next = NULL;
local_save_flags(flags);
local_irq_disable();
reqcnt ++;
if ( 1 == reqcnt )
{
mcutm_reload( USE_TICK_PERIOD );
}
local_irq_restore(flags);
return 0;
}
#define TM_DEBUG 1
#if TM_DEBUG
int call_cnt = 0;
int count = 0;
static void debug_call( void *data )
{
int *cnt = (int *)data;
*cnt ++;
printk( "----test call %dn", *cnt );
if(hw_gpb_in( 1 ))
{
hw_gpb_out( 1,0 );
}
else
{
hw_gpb_out( 1,1 );
}
mcutm_requset( 1, 1000, debug_call, data );
}
#endif
int gpio_open( struct inode *inode, struct file *filp )
{
try_module_get(THIS_MODULE);
if (showmsg) printk(" %s OPENn", DEV_NAME );
return 0;
}
/*-----------------------------------------------------------------------------
설 명 : 초기화
주 의 :
-------------------------------------------------------------------------------*/
// [KERNEL]
//static void __init mcutm_init( void )
static struct file_operations gpio_fops =
{
.open = gpio_open,
.release = gpio_release,
//.ioctl = gpio_ioctl,
};
static void mcutm_init( void )
{
unsigned long tcon;
unsigned long tcnt;
unsigned long tcfg1;
unsigned long tcfg0;
major &= 0xff;
if( !register_chrdev( major, DEV_NAME, &gpio_fops ) )
{
printk(" register device %s OK (major=%d)n", DEV_VERSION, major );
}
else
{
printk(" unable to get major %d for %s n", major, DEV_NAME );
// return -EBUSY;
}
tcnt = 0xffff; /* default value for tcnt */
/* read the current timer configuration bits */
tcon = __raw_readl(S3C2410_TCON);
tcfg1 = __raw_readl(S3C2410_TCFG1);
tcfg0 = __raw_readl(S3C2410_TCFG0);
/* configure clock tick */
tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
tcfg1 |= S3C2410_TCFG1_MUX0_DIV4;
tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
tcfg0 |= S3C2410_TCFG_PRESCALER0_MASK;
tcnt = USE_TICK_PERIOD;
/* timers reload after counting zero, so reduce the count by 1 */
tcnt--;
/* check to see if timer is within 16bit range... */
if (tcnt > 0xffff) {
panic("setup_timer: HZ is too small, cannot configure timer!");
return ;
}
__raw_writel(tcfg1, S3C2410_TCFG1);
__raw_writel(tcfg0, S3C2410_TCFG0);
__raw_writel(tcnt, S3C2410_TCMPB(1));
__raw_writel(tcnt, S3C2410_TCNTB(1));
/* ensure timer is stopped... */
tcon &= ~(0xF<<8);
tcon |= S3C2410_TCON_T1MANUALUPD;
__raw_writel(tcon, S3C2410_TCON);
tcon &= ~(0xF<<8); // One-shot, Inverter off, No operation, Stop
__raw_writel(tcon, S3C2410_TCON);
mcutm_list = kmalloc( sizeof(mcutm_hdl_t)*MAX_REQUEST, GFP_KERNEL );
if ( !mcutm_list )
{
printk( "%s : unable to get memoryn", __FILE__ );
return ;
}
memset( mcutm_list, 0, sizeof(mcutm_hdl_t)*MAX_REQUEST );
if( request_irq( TIMER_A_IRQ, mcutm_interrupt, SA_INTERRUPT, "S3C2410 Timer#0 (falinux)", NULL ) )
{
printk( "%s : unable to get IRQ %dn", __FILE__, TIMER_A_IRQ );
return ;
}
printk( "S3C2410 Timer#0 running (falinux)n" );
hw_gp_init();
#if TM_DEBUG
mcutm_requset( 1, 1000, debug_call, (void *)&call_cnt );
#endif
}
/*-----------------------------------------------------------------------------
설 명 : 초기화
주 의 :
-------------------------------------------------------------------------------*/
static void mcutm_exit( void )
{
free_irq( TIMER_A_IRQ, NULL );
unregister_chrdev( major, DEV_NAME );
printk(" unregister %s OKn", DEV_NAME );
}
module_init(mcutm_init);
module_exit(mcutm_exit);
MODULE_PARM(major , "i");
MODULE_PARM(showmsg, "i");
MODULE_AUTHOR("freefrug@falinux.com");
MODULE_LICENSE("Dual BSD/GPL");
/* end */
===================================
안녕하세요. 박진하 입니다.
아래에 소스를 첨부했는데요..
저번에 제공해주신 Timer 소스를 수정하여 PWM을 사용하려고 합니다.
위에서 작성한 소스중에서 잘못된 부분이 많은거 같은데요..gpio포트 b1을 출력으로 잡았습니다.
Timer1을 PWM으로 사용하는것이구요..
mcutm_init(); 이함수에서
__raw_writel(tcfg1, S3C2410_TCFG1);
__raw_writel(tcfg0, S3C2410_TCFG0);
__raw_writel(tcnt, S3C2410_TCMPB(1));
__raw_writel(tcnt, S3C2410_TCNTB(1));
이부분에서 PWM을 위해 더 설정해주어야 하는 부분은 없는지요..??
그리고 __raw_writel(tcnt, S3C2410_TCMPB(1)); << 이문법이 맞는지요..??
그리고 hw_gp_init(); 이 함수에서..
//B
set_GPIO_OUT(reg_s2410(S3C2410_GPBCON),1);
// 내부 pull-up disable 7..4
reg_s2410(S3C2410_GPBUP) |= 0x00;
// B off
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), 1, 1 );
이렇게 gpio B1포트를 초기화 해주었는데요..
PWM을 출력하기 위해서
rege-gpio.h 헤더파일에서..
/* GPB is 10 IO pins, each configured by 2 bits each in GPBCON.
* 00 = input, 01 = output, 10=special function, 11=reserved
* bit 0,1 = pin 0, 2,3= pin 1...
*
* CPBUP = pull up resistor control, 1=disabled, 0=enabled
*/
#define S3C2410_GPBCON S3C2410_GPIOREG(0x10)
#define S3C2410_GPBDAT S3C2410_GPIOREG(0x14)
#define S3C2410_GPBUP S3C2410_GPIOREG(0x18)
/* no i/o pin in port b can have value 3! */
#define S3C2410_GPB0_INP (0x00 << 0)
#define S3C2410_GPB0_OUTP (0x01 << 0)
#define S3C2410_GPB0_TOUT0 (0x02 << 0)
여기 포트 레지스트 설정중에서 마지막에 define된
#define S3C2410_GPB0_TOUT0 (0x02 << 0)
이 설정은 어떻게 적용하는것인지.. 궁금합니다..
프로젝트가 급한것에 비해..임베디드 시스템을 자세하게 공부할 시간이 많이 부족하네요..
자꾸 부담드리는거 같아서 죄송스럽지만..그래도 부탁드리겠습니다.
조금 자세하게 읽어 주시고 답글 달아주세요..
웹 찾아볼곳은 다 찾아보고..참고할 만한 소스도 다 참고해서 공부하는데도..어렵네요..
바쁘신데 수고많으십니다..좋은하루 보내세요 ^_^;;
파 일 : s3c2410_timer.c
설 명 : S3C2410 의 타이머 0 을 사용하여 등록된 함수를 주기적으로 호출한다
작 성 : 오재경 freefrug@falinux.com
날 짜 : 2005-12-19
수 정 : 장형기 tsheaven@falinux.com
날 짜 : 2007-07-29
주 의 :
-------------------------------------------------------------------------------*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <asm/hardware.h>
#include <asm/arch/regs-timer.h>
#include <asm/arch/regs-irq.h>
#include <asm/arch/regs-gpio.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/ioctl.h>
#include <asm/unistd.h>
#include <asm/io.h>
#include "dev_gpio.h"
#include "s3c2410_timer.h"
#define PCLK 66500000
#define TICKS_PER_SECOND (PCLK/(255+1)/8) //
#define ONE_SEC_CLK (0xFFFF) // 65535 ( TCNTBn ) - Maximuim interval
#define ONE_MSEC_CLK (ONE_SEC_CLK/1000)
#define ONE_100USEC_CLK ((ONE_SEC_CLK/10000)+1)
#define USE_TICK_PERIOD ONE_100USEC_CLK
#define CALCU_TICK_FOR_USEC(x) ( (x) / 100 )
#define TIMER_A_IRQ IRQ_TIMER1
#define MAX_REQUEST 32
#define TIMER_USEC_SHIFT 16
#define DEV_NAME "dev-gpio"
#define DEV_VERSION DEV_NAME" V01"
// 타이머 큐 정보 구조체
typedef struct _mcutm_hdl {
int tick; // 시간계산 카운트
void *data; // 함수호출 인자
void (*routin)( void *); // 인터럽트에서 호출할 함수
struct _mcutm_hdl *next; // 현재 사용하지 않는다
} mcutm_hdl_t;
/*----------------------------------------------------------------------------*/
static mcutm_hdl_t *mcutm_list;
static int reqcnt = 0;
static int showmsg = 0;
static int major = DEV_MAJOR_DEF;
/* implementaion =============================================================*/
#define reg_s2410(x) *(volatile unsigned long *)(x)
#define set_GPIO_IN(reg, nr) reg &= ~(3<<(nr)*2)
#define set_GPIO_OUT(reg, nr) reg &= ~(3<<(nr)*2); reg |= (1<<(nr)*2)
#define GPIO_IN(reg,nr) (reg & (1<<(nr)) ? 1:0)
#define GPIO_OUT(reg,nr,val) reg &= ~(1<<(nr)); reg |= (val&0x1)<<(nr);
/*-----------------------------------------------------------------------------
설 명 : 타이머를 설정한다.
주 의 :
-------------------------------------------------------------------------------*/
static void mcutm_reload( unsigned long tick )
{
unsigned long tcon;
// timer stop
tcon = __raw_readl(S3C2410_TCON);
tcon &= ~(0xF<<8); // Timer 1 = 8
__raw_writel(tcon, S3C2410_TCON);
// Timer 0 Count Buffer Register
__raw_writel(tick, S3C2410_TCMPB(1));
__raw_writel(tick, S3C2410_TCNTB(1));
/* start the timer running */
tcon |= S3C2410_TCON_T1MANUALUPD;
__raw_writel(tcon, S3C2410_TCON);
tcon &= ~(0xF<<8);
tcon |= S3C2410_TCON_T1START;
__raw_writel(tcon, S3C2410_TCON);
}
/*-----------------------------------------------------------------------------
설 명 : GPIO 입출력을 설정한다.
주 의 :
-------------------------------------------------------------------------------*/
void hw_gp_init( void )
{
//F
set_GPIO_IN( reg_s2410(S3C2410_GPFCON), 4 );
set_GPIO_IN( reg_s2410(S3C2410_GPFCON), 5 );
set_GPIO_OUT( reg_s2410(S3C2410_GPFCON), 6 );
set_GPIO_OUT( reg_s2410(S3C2410_GPFCON), 7 );
//B
set_GPIO_OUT(reg_s2410(S3C2410_GPBCON),0);
set_GPIO_OUT(reg_s2410(S3C2410_GPBCON),1);
set_GPIO_OUT(reg_s2410(S3C2410_GPBCON),2);
set_GPIO_OUT(reg_s2410(S3C2410_GPBCON),3);
set_GPIO_OUT(reg_s2410(S3C2410_GPBCON),4);
// 내부 pull-up disable 7..4
reg_s2410(S3C2410_GPFUP) |= 0x00;
reg_s2410(S3C2410_GPBUP) |= 0x00;
// F off
GPIO_OUT( reg_s2410(S3C2410_GPFDAT), 6, 1 );
GPIO_OUT( reg_s2410(S3C2410_GPFDAT), 7, 1 );
// B off
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), 0, 1 );
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), 1, 1 );
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), 2, 1 );
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), 3, 1 );
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), 4, 1 );
}
/*-----------------------------------------------------------------------------
설 명 : GPIO 출력
주 의 :
-------------------------------------------------------------------------------*/
void hw_gpf_out(int gpnr, int val )
{
GPIO_OUT( reg_s2410(S3C2410_GPFDAT), gpnr, val );
}
void hw_gpb_out(int gpnr, int val)
{
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), gpnr, val );
}
/*-----------------------------------------------------------------------------
설 명 : GPIO 입력
주 의 :
-------------------------------------------------------------------------------*/
int hw_gpf_in(int gpnr )
{
return GPIO_IN( reg_s2410(S3C2410_GPFCON), gpnr);
}
int hw_gpb_in(int gpnr )
{
return GPIO_IN( reg_s2410(S3C2410_GPBCON), gpnr);
}
static irqreturn_t mcutm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
mcutm_hdl_t *hdl = mcutm_list;
int loop, mach;
unsigned long tcon;
// Timer 정지
tcon = __raw_readl(S3C2410_TCON);
tcon &= ~(S3C2410_TCON_T1START) | ~(S3C2410_TCON_T1RELOAD);
__raw_writel(tcon, S3C2410_TCON);
mach = reqcnt;
for (loop=0; loop<MAX_REQUEST; loop++ )
{
if ( hdl->tick > 0 )
{
hdl->tick --;
if ( 0 == hdl->tick )
{
if ( hdl->routin ) hdl->routin( hdl->data );
reqcnt --;
}
mach --;
if ( mach <= 0 ) break;
}
hdl ++;
}
if ( 0 < reqcnt )
{
mcutm_reload( USE_TICK_PERIOD );
}
return IRQ_HANDLED;
}
/*-----------------------------------------------------------------------------
설 명 : 핸들러를 등록한다.
주 의 :
-------------------------------------------------------------------------------*/
int gpio_release( struct inode *inode, struct file *filp)
{
module_put(THIS_MODULE);
if (showmsg) printk(" %s CLOSEn", DEV_NAME );
return 0;
}
int mcutm_requset( unsigned int index, int usec, void (*routin)( void *), void *data )
{
mcutm_hdl_t *hdl;
unsigned long flags;
if ( MAX_REQUEST <= index ) return -1;
if ( usec <= 0 ) return -1;
hdl = mcutm_list + index;
hdl->tick = CALCU_TICK_FOR_USEC(usec);
hdl->data = data;
hdl->routin = routin;
hdl->next = NULL;
local_save_flags(flags);
local_irq_disable();
reqcnt ++;
if ( 1 == reqcnt )
{
mcutm_reload( USE_TICK_PERIOD );
}
local_irq_restore(flags);
return 0;
}
#define TM_DEBUG 1
#if TM_DEBUG
int call_cnt = 0;
int count = 0;
static void debug_call( void *data )
{
int *cnt = (int *)data;
*cnt ++;
printk( "----test call %dn", *cnt );
if(hw_gpb_in( 1 ))
{
hw_gpb_out( 1,0 );
}
else
{
hw_gpb_out( 1,1 );
}
mcutm_requset( 1, 1000, debug_call, data );
}
#endif
int gpio_open( struct inode *inode, struct file *filp )
{
try_module_get(THIS_MODULE);
if (showmsg) printk(" %s OPENn", DEV_NAME );
return 0;
}
/*-----------------------------------------------------------------------------
설 명 : 초기화
주 의 :
-------------------------------------------------------------------------------*/
// [KERNEL]
//static void __init mcutm_init( void )
static struct file_operations gpio_fops =
{
.open = gpio_open,
.release = gpio_release,
//.ioctl = gpio_ioctl,
};
static void mcutm_init( void )
{
unsigned long tcon;
unsigned long tcnt;
unsigned long tcfg1;
unsigned long tcfg0;
major &= 0xff;
if( !register_chrdev( major, DEV_NAME, &gpio_fops ) )
{
printk(" register device %s OK (major=%d)n", DEV_VERSION, major );
}
else
{
printk(" unable to get major %d for %s n", major, DEV_NAME );
// return -EBUSY;
}
tcnt = 0xffff; /* default value for tcnt */
/* read the current timer configuration bits */
tcon = __raw_readl(S3C2410_TCON);
tcfg1 = __raw_readl(S3C2410_TCFG1);
tcfg0 = __raw_readl(S3C2410_TCFG0);
/* configure clock tick */
tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
tcfg1 |= S3C2410_TCFG1_MUX0_DIV4;
tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
tcfg0 |= S3C2410_TCFG_PRESCALER0_MASK;
tcnt = USE_TICK_PERIOD;
/* timers reload after counting zero, so reduce the count by 1 */
tcnt--;
/* check to see if timer is within 16bit range... */
if (tcnt > 0xffff) {
panic("setup_timer: HZ is too small, cannot configure timer!");
return ;
}
__raw_writel(tcfg1, S3C2410_TCFG1);
__raw_writel(tcfg0, S3C2410_TCFG0);
__raw_writel(tcnt, S3C2410_TCMPB(1));
__raw_writel(tcnt, S3C2410_TCNTB(1));
/* ensure timer is stopped... */
tcon &= ~(0xF<<8);
tcon |= S3C2410_TCON_T1MANUALUPD;
__raw_writel(tcon, S3C2410_TCON);
tcon &= ~(0xF<<8); // One-shot, Inverter off, No operation, Stop
__raw_writel(tcon, S3C2410_TCON);
mcutm_list = kmalloc( sizeof(mcutm_hdl_t)*MAX_REQUEST, GFP_KERNEL );
if ( !mcutm_list )
{
printk( "%s : unable to get memoryn", __FILE__ );
return ;
}
memset( mcutm_list, 0, sizeof(mcutm_hdl_t)*MAX_REQUEST );
if( request_irq( TIMER_A_IRQ, mcutm_interrupt, SA_INTERRUPT, "S3C2410 Timer#0 (falinux)", NULL ) )
{
printk( "%s : unable to get IRQ %dn", __FILE__, TIMER_A_IRQ );
return ;
}
printk( "S3C2410 Timer#0 running (falinux)n" );
hw_gp_init();
#if TM_DEBUG
mcutm_requset( 1, 1000, debug_call, (void *)&call_cnt );
#endif
}
/*-----------------------------------------------------------------------------
설 명 : 초기화
주 의 :
-------------------------------------------------------------------------------*/
static void mcutm_exit( void )
{
free_irq( TIMER_A_IRQ, NULL );
unregister_chrdev( major, DEV_NAME );
printk(" unregister %s OKn", DEV_NAME );
}
module_init(mcutm_init);
module_exit(mcutm_exit);
MODULE_PARM(major , "i");
MODULE_PARM(showmsg, "i");
MODULE_AUTHOR("freefrug@falinux.com");
MODULE_LICENSE("Dual BSD/GPL");
/* end */
===================================
안녕하세요. 박진하 입니다.
아래에 소스를 첨부했는데요..
저번에 제공해주신 Timer 소스를 수정하여 PWM을 사용하려고 합니다.
위에서 작성한 소스중에서 잘못된 부분이 많은거 같은데요..gpio포트 b1을 출력으로 잡았습니다.
Timer1을 PWM으로 사용하는것이구요..
mcutm_init(); 이함수에서
__raw_writel(tcfg1, S3C2410_TCFG1);
__raw_writel(tcfg0, S3C2410_TCFG0);
__raw_writel(tcnt, S3C2410_TCMPB(1));
__raw_writel(tcnt, S3C2410_TCNTB(1));
이부분에서 PWM을 위해 더 설정해주어야 하는 부분은 없는지요..??
그리고 __raw_writel(tcnt, S3C2410_TCMPB(1)); << 이문법이 맞는지요..??
그리고 hw_gp_init(); 이 함수에서..
//B
set_GPIO_OUT(reg_s2410(S3C2410_GPBCON),1);
// 내부 pull-up disable 7..4
reg_s2410(S3C2410_GPBUP) |= 0x00;
// B off
GPIO_OUT( reg_s2410(S3C2410_GPBDAT), 1, 1 );
이렇게 gpio B1포트를 초기화 해주었는데요..
PWM을 출력하기 위해서
rege-gpio.h 헤더파일에서..
/* GPB is 10 IO pins, each configured by 2 bits each in GPBCON.
* 00 = input, 01 = output, 10=special function, 11=reserved
* bit 0,1 = pin 0, 2,3= pin 1...
*
* CPBUP = pull up resistor control, 1=disabled, 0=enabled
*/
#define S3C2410_GPBCON S3C2410_GPIOREG(0x10)
#define S3C2410_GPBDAT S3C2410_GPIOREG(0x14)
#define S3C2410_GPBUP S3C2410_GPIOREG(0x18)
/* no i/o pin in port b can have value 3! */
#define S3C2410_GPB0_INP (0x00 << 0)
#define S3C2410_GPB0_OUTP (0x01 << 0)
#define S3C2410_GPB0_TOUT0 (0x02 << 0)
여기 포트 레지스트 설정중에서 마지막에 define된
#define S3C2410_GPB0_TOUT0 (0x02 << 0)
이 설정은 어떻게 적용하는것인지.. 궁금합니다..
프로젝트가 급한것에 비해..임베디드 시스템을 자세하게 공부할 시간이 많이 부족하네요..
자꾸 부담드리는거 같아서 죄송스럽지만..그래도 부탁드리겠습니다.
조금 자세하게 읽어 주시고 답글 달아주세요..
웹 찾아볼곳은 다 찾아보고..참고할 만한 소스도 다 참고해서 공부하는데도..어렵네요..
바쁘신데 수고많으십니다..좋은하루 보내세요 ^_^;;