Writing Real-Time Device Drivers for Telecom Switches, Part 2 of 2
Instead of jumping into the organization of files or programming techniques when programming for real time, first evaluate background information. Ask questions about time constraints, message frequencies, buffer sizes and data path dependencies. Also, ask if there is any intelligence built into registers. You will find this information useful when you are in the debugging and implementation stages. The safest way to learn how to write software drivers is to modify an existing driver. Writing one from scratch might be a little hard for a novice writer.
Here are the basic steps for writing a software driver:
Become familiar with the device.
If it's a third-party ASIC, get a sample driver from the vendor and use the sample device driver as a guide.
Consider the issues raised in Part 1 of this article (September/October 2001 issue of ELJ).
Write a skeleton driver, containing only function prototypes and empty implementation. Review the skeleton with team members to see if additional functionality is needed. More importantly, allow for added functionality.
Write your first I/O routine and test it.
Proceed with coding.
There are several ways to structure the hardware access in your HAL layer. You could have functions like _APS_WriteMBRtable() and _APS_ReadCellCounter(), and they will simply talk to the hardware directly via RW_ReadLongWord().
There are also some drivers that define a struct and take a pointer to it and point it at the base address of the device. They simply can dereference the struct pointer as
_APS_Memory->contextTable.entry[12].esot = 1;
Or you could pass all hardware access through a small number of specialized access routines. If these are inlined, there is no performance hit:
_APS_WriteMem() _APS_ReadMem() _APS_WriteReg() _APS_ReadReg()A problem with this is you have less control over what the compiler is doing. Is it doing byte or word reads? How can you control what it does with FIFOs or clear-on-read registers? This choice is not without its disadvantages.
Think of the time it takes to do this:
address = _APS_Base + _APS_tStats; RW_WriteMem(address, value[1]); RW_WriteMem(address+4, value[2]); RW_WriteMem(address+8, value[3]);
vs. the amount of time to do this:
_APS_WriteMem(_APS_tStats, value[1]);
_APS_WriteMem(_APS_tStats+4, value[2]);
_APS_WriteMem(_APS_tStats+8, value[3]);
_APS_WriteMem(longword address, longword value)
{
RW_WriteMem(_APS_Base + address, value);
}
On balance, I'd recommend using a few specialized access routines,
as it allows you great flexibility with few of the problems listed
above and with careful coding and inlining, there is no speed hit.
You also know that all accesses to your device come through this
one gateway giving you better debug ability.
You may have a device that uses mailbox access rather than a memory-mapped structure. Often such mailbox accesses allow you to write multiple values at once. Obviously, it would be inefficient to have a _APS_WriteMem() that accesses the mailbox but only writes one word at a time. But you could have a _APS_WriteEntries(longword data[], longword startAddr, int numEntries) routine that still would be your one point of access as described above. Sometimes your device may allow mailbox access in various sizes (e.g., bytes, words, longwords). You should provide this flexibility.
There are several parts to driver initialization:
Device-driver initialization: memory allocation, global variable initialization, mutex lock creation, etc.
Device initialization: setting registers and memory to startup values.
Device power-up diagnostics: memory, register, interrupt tests, etc.
These should be kept as separate functions so each can be called at the appropriate place during startup. Also, as much as possible, keep initializations free from dependencies on other modules. People are always moving different initializations before and after others, making interdependence a real problem.
When accessing a device that has more than one data path, i.e., four streams of data flowing into it (0-3), you should take extra care in finding out which channels need to be accessed. Let's say we have two slots labeled (0-1), and we have eight ports per slot (0-7). By design we have the following: ports 0-3 on slot ID 0 belong to data path 0, ports 4-7 on slot ID 0 are attached to data path 1, ports 0-3 on slot ID 1 are associated with data path 2 and ports 4-7 on slot ID 1 are connected to data path 3. Notice the importance here of knowing if the numbers are 0- or 1-based. Such a complication in the hardware can lure us to write several conditional if/then/else statements. We can avoid that by plotting a binary table of the required results. Then we can figure out the bit shifting that will help us.
The following piece of code simplifies the table into a couple of register shifts. I am sure that bit shifting can be your friend in many cases, but you have to be careful:
DataPathSelected = (ioSlot<<1) + (PortNumber>>2)
If you plot the table for values of ioSlot ranging from 0-1 and PortNumber 0-7 per I/O card, DataPath will follow Table 1. This will actually give you a map and will always result in a 0 or a 1 indicating the data path required (see Listing 1).
Trending Topics
| You Need A Budget | Feb 10, 2012 |
| The Linux powered LAN Gaming House | Feb 08, 2012 |
| Creating a vDSO: the Colonel's Other Chicken | Feb 06, 2012 |
| Your CMS Is Not Your Web Site | Feb 01, 2012 |
| Casper, the Friendly (and Persistent) Ghost | Jan 31, 2012 |
| Razor-qt 0.4 - Qt based Desktop Environment | Jan 30, 2012 |
- Fun with ethtool
- 100% disappointed with the decision to go all digital.
- Parallel Programming with NVIDIA CUDA
- Readers' Choice Awards 2011
- You Need A Budget
- Linux-Based X Terminals with XDMCP
- Validate an E-Mail Address with PHP, the Right Way
- The Linux powered LAN Gaming House
- Why Python?
- Creating a vDSO: the Colonel's Other Chicken





4 hours 43 min ago
5 hours 44 min ago
15 hours 11 min ago
15 hours 22 min ago
21 hours 26 min ago
1 day 50 min ago
1 day 1 hour ago
1 day 2 hours ago
1 day 7 hours ago
1 day 7 hours ago