Introduction to RTC driver development in WinCE

Source: Internet
Author: User

It's almost the spring festival. It's a little easier. I have just developed the RTC driver in wince6.0. Here I will introduce it.

RTC is a real-time clock ). Currently, most 32-bit processors have their own RTC modules and external RTC modules. Generally, the external RTC is accessed through the I2C bus. If the CPU itself comes with RTC, you can access the RTC module by reading internal registers. If it is external, it will be a little effort, but also write an I2C driver to access the external RTC module.

In wince6.0, the RTC driver is implemented in oal, and the file names are generally called RTC. C. There are three important functions in this file. Once they are implemented, the RTC driver is complete. The functions are as follows:

Bool oemgetrealtime (lpsystemtime lpst): Get the current time

Bool oemsetrealtime (lpsystemtime lpst): sets the current time

Bool oemsetalarmtime (lpsystemtime lpst): sets the alert time.

The parameters of the above three functions are lpst. Here we will introduce them:

Lpsystemtime is actually a pointer to the systemtime structure. The systemtime is defined as follows:

Typedef struct _ systemtime {
Word wyear;
Word wmonth;
Word wdayofweek;
Word wday;
Word whour;
Word wminute;
Word wsecond;
Word wmilliseconds;
} Systemtime;

See, huh, huh.

 

Oemgetrealtime (...) is used to obtain the current time. After wince is started, by default, WinCE calls the oemgetrealtime (...) function at intervals to obtain the system time. This method is called hardware mode. Wince also has another method to get the system time, known as the software mode, which is to accumulate time by calling the gettickcount (...) function to track the changes of the system's timetick. If you want to use the software mode, you need to make the following settings in the registry:

HKEY_LOCAL_MACHINE/platform/"softrtc" = 1

Let me talk about my views. Generally, we need to use the hardware mode, so that the system time obtained is relatively accurate. The system time obtained by the software mode is not accurate.

 

Oemsetrealtime (...) is used to set the current time. After wince is started, we will see the time display in the lower right corner of the interface. We can set the time directly in the wince interface. At this time, the system will call oemsetrealtime (..) write the time you set to the RTC module. We all know that there is a case in the oemiocontrol function named ioctl_hal_init_rtc. This case is used to set the initial value of the real-time clock during initialization, in this case, oemsetrealtime (...) is called (..) function. The reference code is as follows:

Case ioctl_hal_init_rtc:
// The kernel has detected a cold boot.
// The Real-time clock probably needs to be reset.
If (ninbufsize> = sizeof (systemtime ))
Return oemsetrealtime (lpsystemtime) lpinbuf );
Else
Return false;
Break;

 

Oemsetalarmtime (...) is used to set the alarm time. To implement this function, it depends on whether your RTC module has the alarm function. The RTC with the alarm function allows you to set the alarm time. After you set the alarm time, RTC will compare your alarm time with the current time. Once the two times are equal, it will interrupt. This is the general principle. Therefore, this function is actually used to set an alert time and enable the RTC interrupt. Of course, sysintr_rtc_alarm must be returned in the interrupt program ISR. In an application, we can run an application at a specified time by calling cerunappattime. This function seems to call oemsetalarmtime (...) to set the alarm time. I have not tried it.

 

Generally, in wince5.0 and wince6.0, RTC remains unchanged. The only difference is that in wince6.0, all three functions need to be protected by the critical section, which was not previously seen in wince5.0. For example, the following code is based on the real-time clock chip isl1208, which is for reference only:

# Define al_enable 0x80

Critical_section rtc_critsect;
Static unsigned char critical_flag = 1;

Void i2c_init (void );
Void isl1208_init (void );
DWORD i2c_write (unsigned char slaveaddr, unsigned char regaddr, unsigned char * Buf, DWORD num );
Dowrd i2c_read (unsigned char slaveaddr, unsigned char regaddr, unsigned char * Buf, DWORD num );

Bool oemgetrealtime (lpsystemtime lpst)
{
Unsigned char Buf [12];
DWORD flg;

// Retailmsg (1, (_ T (": oemgetrealtime ::::/R/N ")));
If (critical_flag) // The first power-on
{
Initializecriticalsection (& rtc_critsect); // initialize the critical section
I2c_init (); // Initialization
I2C isl1208_init (); // initializes the isl1208 real-time clock chip.
Critical_flag = 0;
}

Entercriticalsection (& rtc_critsect );

Memset (BUF, 0, sizeof (BUF ));
Flg = i2c_read (isl1208, 0x0, Buf, 6); // read the isl1208 time
If (! Flg) // I2C failure, error returned
{
Retailmsg (1, (_ T ("::::::: oemgetrealtime error.../R/N ")));
Return false;
}

Leavecriticalsection (& rtc_critsect );

Buf [2] & = 0x7f; // clear the Mil bit
Lpst-> wsecond = (Word) (BUF [0] & 0x0f) + (BUF [0]> 4) * 10); // obtain the current time, and converts the time from BCD to decimal.
Lpst-> wminute = (Word) (BUF [1] & 0x0f) + (BUF [1]> 4) * 10 );
Lpst-> whour = (Word) (BUF [2] & 0x0f) + (BUF [2]> 4) * 10 );
Lpst-> wday = (Word) (BUF [3] & 0x0f) + (BUF [3]> 4) * 10 );
Lpst-> wmonth = (Word) (BUF [4] & 0x0f) + (BUF [4]> 4) * 10 );
Lpst-> wyear = (Word) BUF [5] + 2000;

Return true;
}

Bool oemsetrealtime (lpsystemtime lpst)
{
Unsigned char Buf [12];
Word year;
DWORD flg;

// Retailmsg (1, (_ T (": oemsetrealtime ::::/R/N ")));

Entercriticalsection (& rtc_critsect );

If (lpst-> wyear> 2000)
{
Year = lpst-& gt; wyear-2000;
}
Else
{
Year = 0;
}
Buf [0] = (lpst-> wsecond)/10) <4) | (lpst-> wsecond) % 10); // set the time, convert decimal to BCD code
Buf [1] = (lpst-> wminute)/10) <4) | (lpst-> wminute) % 10 );
Buf [2] = (lpst-> whour)/10) <4) | (lpst-> whour) % 10 );
Buf [3] = (lpst-> wday)/10) <4) | (lpst-> wday) % 10 );
Buf [4] = (lpst-> wmonth)/10) <4) | (lpst-> wmonth) % 10 );
Buf [5] = (Year/10) <4) | (Year % 10 );
Buf [6] = (unsigned char) lpst-> wdayofweek;
Buf [2] | = 0x80; // set mil bit equal 1
Flg = i2c_write (isl1208, 0x0, Buf, 7 );
If (! Flg)
{
Retailmsg (1, (_ T ("::::::: oemsetrealtime error.../R/N ")));
Return false;
}

Leavecriticalsection (& rtc_critsect );

Return true;
}

Bool oemsetalarmtime (lpsystemtime lpst)
{
Unsigned char Buf [12];
DWORD flg;

// Retailmsg (1, (_ T (": oemsetalarmtime ::::/R/N ")));

Entercriticalsection (& rtc_critsect );

Memset (BUF, 0, sizeof (BUF ));
Buf [1] = (lpst-> wsecond)/10) <4) | (lpst-> wsecond) % 10) | al_enable; // set the alarm register
Buf [2] = (lpst-> wminute)/10) <4) | (lpst-> wminute) % 10) | al_enable;
Buf [3] = (lpst-> whour)/10) <4) | (lpst-> whour) % 10) | al_enable;
Buf [4] = (lpst-> wday)/10) <4) | (lpst-> wday) % 10) | al_enable;
Buf [5] = (lpst-> wmonth)/10) <4) | (lpst-> wmonth) % 10) | al_enable;
Flg = i2c_write (isl1208, 0xc, Buf, 6 );
If (! Flg)
{
Retailmsg (1, (_ T ("::::::: oemsetrealtime error.../R/N ")));
Return false;
}
Flg = * vic2_intenable; // enable external interrupt 1, because the RTC interrupt output is connected to the processor's External Interrupt 1
Flg | = int2_ext1;
* Vic2_intenable = flg;

Leavecriticalsection (& rtc_critsect );

// Return true if alarm set, false otherwise
Return true;
}

DWORD isl1208_init (void)
{
DWORD flg;
Unsigned char Buf [12];

Memset (BUF, 0, sizeof (BUF ));
Flg = i2c_read (isl1208, 0x0, Buf, 6 );
If (! Flg)
{
Retailmsg (1, (_ T ("::::::: isl1208_init error.../R/N ")));
Return false;
}

If (BUF [0]! = 0) | (BUF [1]! = 0) | (BUF [2]! = 0) | (BUF [3]! = 0) | (BUF [4]! = 0) | (BUF [5]! = 0 ))
{// The time has been set to prove that isl1208 has been initialized and returns directly
Return true;
}

Buf [0] = status_wrtc | status_arst;
Flg = i2c_write (isl1208, 0x7, Buf, 1, 0); // sets the isl1208 Status control register.
Delayinmsec (1 );

Buf [0] = int_alme | 0x80; // enable the isl1208 alarm function, interrupt output, and trigger at a time
Flg = i2c_write (isl1208, 0x8, Buf, 1, 0); If (! Flg)
{
Retailmsg (1, (_ T ("::::::: oemsetrealtime error.../R/N ")));
Return false;
}

Buf [0] = default_second | al_enable; // set the alarm register and the alarm time. The default value is set here.
Buf [1] = default_minute | al_enable ;//
Buf [2] = default_hour | al_enable;
Buf [3] = default_date | al_enable;
Buf [4] = (default_month + 1) | al_enable;
Flg = i2c_write (isl1208, 0xc, Buf, 5, 0 );
If (! Flg)
{
Retailmsg (1, (_ T ("::::::: I2C write error.../R/N ")));
Return 0;
}

Buf [0] = default_second; // set the system time. The default time is set here.
Buf [1] = default_minute;
Buf [2] = default_hour;
Buf [3] = default_date;
Buf [4] = default_month;
Buf [5] = default_year;
Buf [6] = default_week;
Flg = i2c_write (isl1208, 0x0, Buf, 7, 0); If (! Flg)
{
Retailmsg (1, (_ T ("::::::: I2C write error.../R/N ")));
Return 0;
}

Return 1;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.