How to create an oal for programming at the OEM Adaptation Layer in WinCE

Source: Internet
Author: User

[Data Source]: http://motion.chinaitlab.com/WINCE/30568.html

I don't know who the author of this article is. These websites seem very irresponsible, even the author's name is not left, too much

 

As mentioned in CE's help document, creating oal is a very complex task, and the common method is to copy the oal code of the original same platform, and then modify it to adapt to the special requirements of the platform. That is to say, for platforms without special requirements, it is sufficient to copy the oal code of the original platform. Due to the complexity of oal, I will only explain the common parts in this article.
  
1. ISR implementation
  
1. ISR Concept
  
ISR (interrupt service routine) is a program that processes irqs (interrupt request line. Windows CE uses an ISR to process all IRQ requests. When an interrupt occurs, the kernel exception handler first calls the kernel ISR, the kernel ISR disables all interrupts with the same priority and lower priority, and then calls the registered oal ISR program, ISR has the following features:
  
1) execute the minimum interrupt processing. The minimum Interrupt Processing refers to the hardware that can test and reply to interrupt, and leave more processing work to the IST (interrupt service thread ).
  
2) return the interrupt ID when ISR is complete (most of the interrupt IDs are predefined ).
  
2. isr structure of the x86 Platform
  
The ISR of the X86 platform is stored in % _ winceroot %/public/common/oak/CSP/I .pdf/oal/fwpc. C. The function name is perpisr. The following describes the main code of this function:
  
Ulong perpisr (void)
{
Ulong ulret = sysintr_nop; // return value, that is, the interrupt ID (prefix with sysintr)
Uchar uccurrentinterrupt; // The current interrupt number.
If (fintrtime) //// fintrtime is used to test the extended time of srand ist. the test tool is iltiming.exe.
......
Uccurrentinterrupt = picgetcurrentinterrupt (); // return the current interrupt IRQ
If (uccurrentinterrupt = intr_timer0) // irq0, irq0 indicates system clock interruption. For details, see "2. Implement system clock"
......
If (dwrebootaddress) /// do you want to restart
Reboothandler ();
......
If (uccurrentinterrupt = intr_rtc) // irq8, real-time clock interruption
......
Else if (uccurrentinterrupt <= intr_maximum) // If the interrupt is less than intr_maximum
{
Ulret = nkcallintchain (uccurrentinterrupt); // call the interrupt chain
If (ulret = sysintr_chain) // if the chain is not interrupted
Ulret = oemtranslateirq (uccurrentinterrupt); // Convert Between IRQ and sysintr. This function returns the sysintr of IRQ.
......
Picenableinterrupt (uccurrentinterrupt, false); // enable all interrupts except the current one
} // Else if
Oemindicateintsource (ulret); // notifies the kernel that sysintr is interrupted.
}
  
From the above Code, it is not difficult to see that the ISR task is to return the interrupt ID prefixed with "sysintr _". If you do not need to execute the IST, then sysintr_nop is returned.
  
3. interrupted registration steps
  
Refer to the code of the X86 platform. The steps for stopping registration are as follows:
  
1) Use the setup_interrupt_map macro to associate sysintr and IRQ. Constants prefixed with "sysintr _" are used by the kernel to uniquely identify the interrupted hardware. Some sysintr is pre-defined in the nkintr. h file. OEMs Can Customize sysintr in the oalintr. h file.
  
2) use the hookinterrupt function to associate the hardware interrupt number and ISR. The hardware interrupt number is the physical interrupt number, not the logical interrupt number IRQ. The hookinterrupt function is called at the end of the initpics function (which is located in the same file as the ISR above), as shown below:
  
For (I = 64; I <80; I ++)
Hookinterrupt (I, (void *) perpisr); // associate 16 interrupt numbers with ISR
  
4. interrupt handling steps
  
1) Call the interruptinitialize function to associate sysintr with ist, which is an event associated with the IST waiting. Generally, write the following code in the driver:
  
Hevent = createevent (...) // create an event object
Interruptinitialize (sysintr_serial, hevent,...) // associate a serial interrupt ID with this event
Hthd = createthread (..., myistroutine, hevent,...) // create a thread (IST)
Cesetthreadpriority (hthd, 152); // improves the priority of this thread
  
2) ist performs the I/O operation. Generally, ist is written as follows:
  
For (;) // The driver is always in the service status
{
Waitforsingleobject (hevent, infinite); // infinite wait event
... // I/O operation
Interruptdone (interruptid); // ends the current Interrupt Processing
}
  
3) data transmission between ISR and ist
  
If we want to frequently read data from a device and read a small amount each time, calling ist for each read will reduce the performance. As a solution, ISR can read data (stored in the buffer) and read data from the IST to the buffer when the buffer is full. Because ISR runs in kernel mode and ist runs in user mode, ist cannot access the ISR buffer easily, for this reason, Ce provides a method (see the help document titled "passing data between an ISR and an ist"). You can also go to the Tianji embedded development forum to ask.
  
Ii. Implement system clock
  
1. system clock Concept
  
The system clock is the only interrupt (irq0) required by the kernel. The system clock is interrupted every millisecond. When the interrupt occurs, the kernel accumulates in the ISR, And the multiples of 1000 are one second later. In the ISR that processes the system clock, it must not only count the total number, but also determine whether to notify the kernel to start rescheduling all the current threads. To implement an oal, the system clock is the first thing that must be done.
  
2. Processing of clock interruptions on the X86 platform the system clock is initialized by the initclock function, which is generally called in the oeminit function. When an interruption occurs, ISR calculates the total number using the following statements:
  
Curmsec + = system_tick_ms; // system_tick_ms = 1
  
Then, determine the value to be returned based on the following statements:
  
If (INT) (dwreschedtime-curmsec)> = 0)
Return sysintr_resched; // reschedule
Else
Return sysintr_nop; // No operation is performed.
  
In the above Code, the global variable dwreschedtime is defined in Schedule. C, that is, the scheduling module of the kernel determines when to start the re-scheduling thread. Curmsec accumulates the total number of system tick instances generated from WindowsCE startup to the current time. After the system clock is implemented, the oemidle function is also implemented. When no thread is ready to run, the oemidle function is called. The oemidle function places the CPU in idle mode, but the system clock is still accumulated in idle mode.
  
Iii. I/O control code
  
1. I/O control code
  
Applications or drivers can call the kerneliocontrol function to communicate with the oal layer, while kerneliocontrol calls the oemiocontrol function internally. Oemiocontrol is an oal API. OEMs can write their own I/O control code in oemiocontrol to implement some functions or communicate with application software. Common examples of I/O Control Code include restarting a computer, obtaining system information, setting RTC, and obtaining device ID. There are also some special I/O control codes used by system programs. The device ID method provided by CE is not valid.
  
2. Write your own I/O control code steps
  
1) In pkfuncs. h or a new. h file, define it in the following format:
  
# Define ioctl_my_control ctl_code (file_device_hal, 3000, method_neither, file_any_access)
  
2) modify the oemiocontrol function in oemioctl. C and add the following code:
  
Case ioctl_my_control:
  
......
  
  
3) Call the kerneliocontrol function in the application. For detailed parameters, see the help documentation.
  
Conclusion:
  
For descriptions of all oal interface functions and global variables, see the help document titled "supported oal APIs. The oemloadinit_t poemloadinit and oemloadmodule_t poemloadmodule described in the previous article "encrypted Windows CE system" are the global variables exposed by oal for creating trusted environments, after the function is compiled, the function address can be assigned to the two variables. OAL is indeed very complicated. We will study a specific part only when necessary, because the research with problems is the most efficient. I hope these two articles will help developers who are more familiar with oal to publish their own research results and share them with you.

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.