茶叶冷藏温度多少合适:linux rtc 实时时钟驱动

来源:百度文库 编辑:中财网 时间:2024/04/28 20:25:00

源代码文件

//////////////////////////////////////////////////////////////////////////
//      FILE  : tartc.c
//      DATE   : 09/02/2010
//      DESCRIPTION : tamedia real time clock driver source
//      OS : Linux
//      AUTHOR :  rui
//////////////////////////////////////////////////////////////////////////
#include
#include
#include
#include
#include
#include

#if !defined(CONFIG_TANGOX)
#error "Unsupport architecture (TANGOX only)."
#elif defined(CONFIG_TANGO2_SMP863X) && (EM86XX_REVISION < 4)
#error "Unsupport Tango2 (ES4 or above) or Tango3 chip."
#endif /*  */

#include

#ifdef CONFIG_TANGO2
#include
#elif defined(CONFIG_TANGO3)
#include
#endif /*  */


#define GPIO_IIC_SCL        0
#define GPIO_IIC_SDA        1

#define I2C_M41T81_ADDRESS 0xd0

#define SCL_H  { em86xx_gpio_write( GPIO_IIC_SCL, 1 ) ; }
#define SCL_L  { em86xx_gpio_write( GPIO_IIC_SCL, 0 ) ; }
#define SDA_H  { em86xx_gpio_write( GPIO_IIC_SDA, 1 ) ; }
#define SDA_L  { em86xx_gpio_write( GPIO_IIC_SDA, 0 ) ; }
#define SDA_IN  { em86xx_gpio_setdirection ( GPIO_IIC_SDA, GPIO_INPUT ) ; }
#define SDA_OUT { em86xx_gpio_setdirection ( GPIO_IIC_SDA, GPIO_OUTPUT ) ; }
#define WHILE_SDA_HIGH (em86xx_gpio_read( GPIO_IIC_SDA ) == 1 )

MODULE_DESCRIPTION ( "EM86xx/SMP86xx tamedia rtc m41t81 driver\n" ) ;
MODULE_AUTHOR ( "rui" ) ;
MODULE_LICENSE ( "GPL" ) ;

#define TARTC_DEV_NAME "tartc"
static int major = 220 ;
module_param( major, int, 0 ) ;

unsigned int ByteDelayTimeout = 0x1000 ;
unsigned int BitDelayTimeout = 0x200 ;

static void ByteDelay ( void ) ;
static void BitDelay ( void ) ;

static int tartc_open ( struct inode *, struct file * ) ;
static int tartc_release ( struct inode *, struct file * ) ;
static int tartc_read ( struct file *, char *, size_t, loff_t * ) ;
static int tartc_write ( struct file *, const char *, size_t, loff_t * ) ;

static void InterfaceInit ( void ) ;
static void I2C_Start ( void ) ;
static void I2C_Stop ( void ) ;
static void I2C_Ack ( void ) ;
static void I2C_Nack ( void ) ;

struct rtc_private
{
 int ref_cnt ;
 spinlock_t lock ;
} ;

static struct rtc_private rtc_priv ;

static struct file_operations rtc_fops =
{
 .owner = THIS_MODULE,
 .open = tartc_open,
 .read = tartc_read,
 .write = tartc_write,
 .release =tartc_release,
} ;

static void I2C_Start ()
{
 SDA_OUT ;
 SDA_H ;
 BitDelay () ;
 SCL_H ;
 BitDelay () ;
 SDA_L ;
 BitDelay () ;
 SCL_L ;
 BitDelay () ;
}

static void I2C_Stop ()
{
 SDA_OUT ;
 SDA_L ;
 BitDelay () ;
 SCL_H ;
 BitDelay () ;
 SDA_H ;
 BitDelay () ;
}

static void I2C_Ack()
{
 SDA_OUT ;
 SDA_L ;
 BitDelay () ;
 SCL_H ;
 BitDelay () ;
 SCL_L ;
 BitDelay () ;
}

static void I2C_Nack ()
{
 SDA_OUT ;
 SDA_H ;
 BitDelay () ;
 SCL_H ;
 BitDelay () ;
 SCL_L ;
 BitDelay () ;
}

static unsigned char Write_I2C_Byte ( char byte )
{
 char i ;

 SDA_OUT ;
 for ( i = 0 ; i < 8 ; i++ )
 {
  if ( (byte & 0x80) == 0x80 )
  {
   SDA_H ;
  }
  else
  {
   SDA_L ;
  }
  BitDelay () ;
  SCL_H ;
  BitDelay () ;
  SCL_L ;
  byte <<= 1 ;
 }
 
 return (unsigned)1 ;
}

static unsigned char Read_I2C_Byte ( void )
{
 unsigned char i, buff = 0 ;

 for ( i = 0 ; i < 8 ; i++ )
 {
  SDA_OUT ;
  SDA_H ;
  BitDelay () ;
  SCL_H ;
  BitDelay () ;
  SDA_IN ;
  if ( WHILE_SDA_HIGH )
  {
   buff |= 0x01 ;
  }
  if ( i < 7 )
  {
   buff <<= 1 ;
  }
  
  SCL_L ;
  BitDelay () ;
 }
 
 return buff ;
}

static void ByteDelay ( void )
{
 volatile unsigned int dwTimeout ;
 dwTimeout = ByteDelayTimeout ;

 while ( --dwTimeout )
 {
  asm ( "nop" ) ;
 }
}

static void BitDelay ( void )
{
 volatile unsigned int dwTimeout ;
 dwTimeout = BitDelayTimeout ;

 while ( --dwTimeout )
 {
  asm ( "nop" ) ;
 }
}

static void InterfaceInit ( void )
{
 em86xx_gpio_setdirection ( GPIO_IIC_SDA, GPIO_OUTPUT ) ;
 em86xx_gpio_setdirection ( GPIO_IIC_SCL, GPIO_OUTPUT ) ;
 em86xx_gpio_write ( GPIO_IIC_SDA, 1 ) ;
 em86xx_gpio_write ( GPIO_IIC_SCL, 1 ) ;

 ByteDelay () ;
 ByteDelay () ;
 ByteDelay () ;

 I2C_Start () ;
 Write_I2C_Byte ( I2C_M41T81_ADDRESS ) ;
 I2C_Ack () ;
 Write_I2C_Byte ( 0x0c ) ;
 I2C_Ack () ;
 Write_I2C_Byte ( 0x00 ) ;
 I2C_Ack () ;
 I2C_Stop () ;
}

static int tartc_open ( struct inode *inode_ptr, struct file *fptr )
{
 if ( rtc_priv.ref_cnt != 0 )
 {
  printk ( "%s: exclusive access only\n", TARTC_DEV_NAME ) ;
  return -EIO ;
 }

 rtc_priv.ref_cnt++ ;
 fptr->f_op = &rtc_fops ;
 fptr->private_data = (void *) &rtc_priv ;
 
 return 0 ;
}

static int tartc_release ( struct inode *inode_ptr, struct file *fptr )
{
 struct rtc_private *priv = (struct rtc_private *) fptr->private_data ;

 priv->ref_cnt-- ;

 return 0 ;
}

static int tartc_read (struct file *fptr, char *buffer, size_t count, loff_t * fp)
{
 struct rtc_private *priv = (struct rtc_private *) fptr->private_data ;
 unsigned char data[8], ret ;

 if ( count < 8 )
 {
  printk ( "%s: read size must be (%d)\n", TARTC_DEV_NAME, 2 ) ;
  
  return -EIO ;
 }

 spin_lock ( &priv->lock ) ;

 I2C_Start () ;
 Write_I2C_Byte ( I2C_M41T81_ADDRESS ) ;
 I2C_Ack () ;
 Write_I2C_Byte ( 0x00 ) ;
 I2C_Ack () ;

 I2C_Start () ;
 Write_I2C_Byte ( I2C_M41T81_ADDRESS + 1 ) ;
 I2C_Ack () ;

 for (ret = 0; ret < 8; ret++)
 {
  data[ret] = Read_I2C_Byte () ;
  I2C_Ack () ;
 }
 Read_I2C_Byte () ;
 I2C_Nack () ;
 I2C_Stop () ;

 spin_unlock ( &priv->lock ) ;

 if ( ret == 0 )
 {
  return -EFAULT ;
 }

 if ( copy_to_user ( buffer, (char *) &data, 8 ) )
 {
  return -EFAULT ;
 }
 
 return 8 ;
}

static int tartc_write ( struct file *fptr, const char *bufptr, size_t size, loff_t * fp )
{
 struct rtc_private *priv = (struct rtc_private *) fptr->private_data ;
 unsigned char data[8], ret ;

 if ( size != 8 )
 {
  printk ( "%s: write size must be 88888888\n", TARTC_DEV_NAME ) ;
  return -EIO ;
 }
 else if ( copy_from_user ((char *) data, bufptr, size) )
 {
  return -EFAULT ;
 }

 spin_lock ( &priv->lock ) ;


 I2C_Start () ;
 Write_I2C_Byte (I2C_M41T81_ADDRESS ) ;
 I2C_Ack () ;
 Write_I2C_Byte ( 0x00 ) ;
 I2C_Ack () ;
 for ( ret = 0; ret < 8; ret++ )
 {
  Write_I2C_Byte ( data[ret] ) ;
  I2C_Ack () ;
 }
 I2C_Stop () ;

 spin_unlock ( &priv->lock ) ;

 if ( ret == 0 )
 {
  return -EFAULT ;
 }
 return size ;
}


static int tartc_init ( void )
{
 int status = 0 ;

 memset ( &rtc_priv, 0, sizeof (struct rtc_private) ) ;
 InterfaceInit () ;
 spin_lock_init ( &rtc_priv.lock ) ;
 status = register_chrdev (major, TARTC_DEV_NAME, &rtc_fops) ;

 if ( status < 0 )
 {
  printk ( "%s: cannot get major number\n", TARTC_DEV_NAME ) ;
  return status ;
 }
 else if ( major == 0 )
 {
  major = status ;
 }
 
 return 0 ;
}

static void tartc_exit ( void )
{
 unregister_chrdev ( major, TARTC_DEV_NAME) ;
}

module_init ( tartc_init ) ;
module_exit ( tartc_exit ) ;

 

makefile

kerdir=/root/8655/smp86xx_kernel_source_R2.6.22-19/linux-2.6.22.19/

obj-m := tartc.o

modules:
 $(MAKE) -C $(kerdir) M=$(shell pwd) modules

clean:
     rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

 

 

 

测试程序

#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std ;

struct TimeMode_RTC
{
 unsigned int Year;
 unsigned int Month;
 unsigned int DayOfMonth;
 unsigned int DayOfWeek;
 unsigned int Hour;
 unsigned int Minute;
 unsigned int Second;
} ;


int rtcHandle;


bool InitRtcSdk ( void )
{
 rtcHandle = open ("/dev/tartc", O_RDWR);
 if ( rtcHandle == -1 )
 {
  printf( "Open device tartc failed ." ) ;
  return false ;
 }
 
 return  true;
}

bool DeinitRtcSdk ( void )
{
 if ( rtcHandle != -1 )
 {
  close (rtcHandle);
 }
 
 return true ;
}

bool RtcSetDateTime (TimeMode_RTC * pRtc)
{
 __u8 timedata[8];
 int ret;

 //0.1seconds, 0.01 seconds
 timedata[0] = 0x00;
 //ST: stop bit,must be 0. 10seconds,seconds, BCD format.
 timedata[1] = ((((pRtc->Second) / 10) << 4) + ((pRtc->Second) % 10)) & 0x7f;
 //0, 10minutes,minutes
 timedata[2] = ((((pRtc->Minute) / 10) << 4) + ((pRtc->Minute) % 10)) & 0x7f;
 //CEB,CB,10HOURS,hours(24 hour format)
 timedata[3] = ((((pRtc->Hour) / 10) << 4) + ((pRtc->Hour) % 10)) & 0x3f;
 //day of week
 timedata[4] = (pRtc->DayOfWeek) & 0x07;
 //day of month
 timedata[5] = ((((pRtc->DayOfMonth) / 10) << 4) + ((pRtc->DayOfMonth) % 10)) & 0x3f;
 // month
 timedata[6] = ((((pRtc->Month) / 10) << 4) + ((pRtc->Month) % 10)) & 0x1f;
 // year
 timedata[7] = ((((pRtc->Year) % 100) / 10) << 4) + ((((pRtc->Year) % 100)) % 10);

 ret = write (rtcHandle, timedata, 8);
 if ( ret != 8 )
 {
  printf( "Write device tartc0 failed ." ) ;
  return false ;
 }
 
 return true ;
}

bool RtcGetDateTime (TimeMode_RTC * pRtc)
{
 __u8 timedata[8];
 int ret;
 
 ret = read (rtcHandle, timedata, 8);
 if (ret != 8)
 {
  printf( "Read device tartc0 failed ." ) ;
  return false ;
 }
 pRtc->Year = 2000 + ((timedata[7] & 0xf0) >> 4) * 10 + (timedata[7] & 0x0f);
 pRtc->Month = ((timedata[6] & 0x10) >> 4) * 10 + (timedata[6] & 0x0f);
 pRtc->DayOfMonth = ((timedata[5] & 0x30) >> 4) * 10 + (timedata[5] & 0x0f);
 pRtc->DayOfWeek = timedata[4] & 0x07;
 pRtc->Hour = ((timedata[3] & 0x30) >> 4) * 10 + (timedata[3] & 0x0f);
 pRtc->Minute = ((timedata[2] & 0x70) >> 4) * 10 + (timedata[2] & 0x0f);
 pRtc->Second = ((timedata[1] & 0x70) >> 4) * 10 + (timedata[1] & 0x0f);
 
 return true;
}

void TimeCheck(TimeMode_RTC &rtc)
{
 if ( rtc.Year < 2009 || rtc.Year > 2037 )
 {
  cout << "rtc> Year wrong : 2009 ~ 2037 is ok ." << endl ;
  rtc.Year = 2009 ;
 }

 if ( rtc.Month < 1 || rtc.Month > 12 )
 {
  cout << "rtc> Month wrong ." << endl ;
  rtc.Month = 1 ;
 }

 if ( rtc.DayOfMonth< 1 || rtc.DayOfMonth > 31 )
 {
  cout << "rtc> Day wrong." << endl ;
  rtc.DayOfMonth = 1 ;
 }


 if ( rtc.Hour < 0 || rtc.Hour > 23)
 {
  cout << "rtc> Hour wrong ." << endl ;
  rtc.Hour = 0 ;
 }

 if ( rtc.Minute < 0 || rtc.Minute > 59 )
 {
  cout << "rtc> Minute wrong ." << endl ;
  rtc.Minute = 0 ;
 }
 
 if ( rtc.Second < 0 || rtc.Second > 59 )
 {
  cout << "rtc> Second wrong ." << endl ;
  rtc.Second = 0 ;
 }
}

int main (int argc, char *argv[])
{
 TimeMode_RTC rtc ;

 InitRtcSdk ();

 if ( argc != 1 && argc != 7 )
 {
  cout << "Usage :" << endl ;
  cout << "  Get : $rtc" << endl ;
  cout << "  Set : $rtc year month day hour minute second " << endl ;
  
  return EXIT_FAILURE ;
 }
 
 if ( argc == 7 )
 {  
  memset (&rtc, 0, sizeof (TimeMode_RTC)) ;
  
  // year
  for ( int i = 0 ; i < (int)strlen( argv[1] ) ; i++ )
  {
   if ( !isdigit( argv[1][i] ) )
   {
    cout << "The charactors of year you input are not all digits ." << endl ;
    return EXIT_FAILURE ;
   }
  }
  sscanf ( argv[1], "%u", &rtc.Year ) ;

  
  // month
  for ( int i = 0 ; i < (int)strlen( argv[2] ) ; i++ )
  {
   if ( !isdigit( argv[2][i] ) )
   {
    cout << "The charactors of month you input are not all digits ." << endl ;
    return EXIT_FAILURE ;
   }
  }
  sscanf ( argv[2], "%u", &rtc.Month ) ;

  
  // day
  for ( int i = 0 ; i < (int)strlen( argv[3] ) ; i++ )
  {
   if ( !isdigit( argv[3][i] ) )
   {
    printf( "the charactors of day you input are not all digits ." ) ;
    return EXIT_FAILURE ;
   }
  }
  sscanf ( argv[3], "%u", &rtc.DayOfMonth ) ;


  // hour
  for ( int i = 0 ; i < (int)strlen( argv[4] ) ; i++ )
  {
   if ( !isdigit( argv[4][i] ) )
   {
    printf( "the charactors of hour you input are not all digits ." ) ;
    return EXIT_FAILURE ;
   }
  }
  sscanf ( argv[4], "%u", &rtc.Hour ) ;


  // minute
  for ( int i = 0 ; i < (int)strlen( argv[5] ) ; i++ )
  {
   if ( !isdigit( argv[5][i] ) )
   {
    printf( "the charactors of minute you input are not all digits ." ) ;
    return EXIT_FAILURE ;
   }
  }
  sscanf ( argv[5], "%u", &rtc.Minute ) ;

  
  // second
  for ( int i = 0 ; i < (int)strlen( argv[6] ) ; i++ )
  {
   if ( !isdigit( argv[6][i] ) )
   {
    printf( "the charactors of second you input are not all digits ." ) ;
    return EXIT_FAILURE ;
   }
  }
  sscanf ( argv[6], "%u", &rtc.Second ) ;

  TimeCheck( rtc ) ;

  RtcSetDateTime (&rtc);
 }

 
 memset (&rtc, 0, sizeof (TimeMode_RTC));
 RtcGetDateTime (&rtc); 
 TimeCheck( rtc ) ;
 DeinitRtcSdk ();

 struct tm when ;
 ////mktime
 when.tm_year = rtc.Year - 1900;
 when.tm_mon = rtc.Month - 1;
 when.tm_mday = rtc.DayOfMonth;
 when.tm_hour = rtc.Hour ;
 when.tm_min = rtc.Minute;
 when.tm_sec = rtc.Second;

 time_t timep = mktime( &when ) ;
 stime(&timep); 

 cout << "Current time : " << rtc.Year << "-" << rtc.Month << "-" << rtc.DayOfMonth << " " << rtc.Hour << ":" << rtc.Minute << ":" << rtc.Second << endl ;

 return EXIT_SUCCESS ;
}