1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
This driver will support the HostMot2 firmware on the following boards:
EPP:
7i43 (Xilinx Spartan 3, 200 K or 400 K gates (can query which from the CPLD))
PCI:
5i20 (Xilinx Spartan 2, 200 K gates, PLX 9030, Subsystem ID 3131)
5i22-1 (Xilinx Spartan 3, 1.0 M gates, PLX 9054, Subsystem ID 3314)
5i22-1.5 (Xilinx Spartan 3, 1.5 M gates, PLX 9054, Subsystem ID 3313)
5i23 (Xilinx Spartan 3, 400 K gates, PLX 9054, Subsystem ID 3315)
PC/104-Plus:
4i65 (Xilinx Spartan 2, 200 K gates, PLX 9030, Subsystem ID 3132)
4i68 (Xilinx Spartan 3, 400 K gates, PLX 9054, Subsystem ID 3311 (was 3133))
Watchdog:
Timeout is set by the watchdog.timeout_ns parameter. It's a u32,
which makes a maximum timeout 4,294,967,295 ns, or about 4.3 seconds.
Pins, IOPorts, and GPIOs:
Pins are the little pieces of metal at the connectors that carry
signals. Pins are described by the Pin Descriptor array in the
firmware. Each pin has a Pin Descriptor (PD). Each pin is connected
to one or two module instances: an IOPort instance and (optionally)
some instance of some other module. The IOPort is considered the
"primary" user of the pin, and the other module instance (if any)
is considered the secondary user. The PD specifies which module
(if any) is the secondary user of this pin, which instance of that
module, which of the module instance's pins it is, and whether the
module instance uses the pin as an input or an output. (See the
hostmot2 register map for the specifics.) The IOPort instance that
is the primary user has a register that selects whether the pin is
driven by the primary or the secondary user. This setting is chosen
by the user at module load time, by specifying the config string.
IOPorts are instances of the IOPort Module. Each IOPort instance
governs the pins on one I/O connector (24 pins per connector).
GPIOs are the HAL representations of pins. Not all pins will have a
corresponding GPIO, and not all GPIOs look the same. For example,
pins that are governed by a module instance may be configured (by
that module instance) as either input or output, and that setting
is not changeable by the user and not exported to HAL.
Architecture:
load the hostmot2 module, it does nothing but export a couple of kernel
functions for the low-level drivers to use
load the low-level driver(s) for the board-type(s) you want to use
(hm2_7i43 and/or hm2_pci), giving each a config string array modparam
the board-driver setup does this:
find the board(s)
for each board found:
initialize an hm2_lowlevel_io_t (llio)
pass the llio and the board's config string to the
hm2_register() function (in the hostmot2 driver), which
does this:
allocate a hostmot2_t struct to hold this running instance
of the hostmot2 firmare, add the hm2_lowlevel_io_t to it
parse the config string
fetch the specified firmware, call the llio to program the fpga
call llio to read the IDROM header, Pin Descriptors,
and Module Descriptors into the hm2_t
parse & validate the idrom header
parse the MDs: walk the list of MDs read, calling
the module drivers to validate each one (skip unknown
MDs, and fail the load if any invalid MDs are found).
Each module driver does this:
verify MD is consistent (ie, all MD fields match
expected values)
verify this is the first MD of this GTAG (type)
we've seen (ie, there can be only one encoder MD,
one pwmgen MD, etc)
Do any module-specific sanity checks
Initialize the module structure in the hm2
register tram read/write regions
allocate an initialize all non-tram register buffers
and any extra memory the module driver needs
export HAL objects, initialize pin & param values
(FIXME: ioport can't do it here)
return number of module instances actually used
Allocate tram buffers (based on module-drivers'
registrations from the previous step)
Configure the pins owned by the active module instances (source & direction)
export & initialize gpio HAL objects (hm2->pin)
set up the raw interface, if enabled (export & initialize Raw HAL objects)
hm2_force_write (tell all module-drivers to write
their internal representation out to the hardware; this
completely configures the non-tram parts of the hardware)
read the tram, tell each module driver to initialize its
read-tram structures, then tell each one to process the
(same) read-tram buffer
tell each module driver to initialize its write-tram
structures, then tell each one to prepare a tram write,
then write the tram
export the main read/write functions
if the llio claims to be threadsafe, export the gpio
read/write functions
FIXME: ok down to here
the per-board HAL-exported read/write functions are generic hm2
functions that use board-specific i/o functions (hm2_lowlevel_io_t).
Each generic hm2 function is exported to HAL once for each hm2
instance that can use it. Each HAL function is the same hm2 function
with different hostmot2_t's for arguments.
At runtime, it will eventually be desirable to use the TranslationRAM
to map all the on-board registers to be consecutive, and do a single
bulk transfer to read all the stuff into the driver.
Shout outs:
Thanks to Peter Wallace at Mesa Electronics for supporting the
development of this driver.
Thanks to Jeff Epler for the initial encoder index code.
Thanks to John M Kasunich, Steven W Padnos, and Paul Corner for help
with RTAI and LinuxCNC internals, and everything else.
Thanks to Eric Johnson for lots of early testing and debugging.
Thanks to Jeffry Molanus (U. Twente) for the anyio driver, it provided
some early inspiration.
|