Merge lp:~dirk.zimoch/epics-base/fix-aai-and-aao into lp:~epics-core/epics-base/3.14
- fix-aai-and-aao
- Merge into 3.14
Status: | Merged |
---|---|
Approved by: | Andrew Johnson |
Approved revision: | 12079 |
Merge reported by: | Andrew Johnson |
Merged at revision: | not available |
Proposed branch: | lp:~dirk.zimoch/epics-base/fix-aai-and-aao |
Merge into: | lp:~epics-core/epics-base/3.14 |
Diff against target: |
895 lines (+434/-101) 10 files modified
documentation/RELEASE_NOTES.html (+7/-0) src/dev/softDev/Makefile (+2/-0) src/dev/softDev/devAaiSoft.c (+87/-0) src/dev/softDev/devAaoSoft.c (+79/-0) src/dev/softDev/devSoft.dbd (+2/-0) src/misc/base.dbd (+2/-0) src/rec/aaiRecord.c (+103/-52) src/rec/aaiRecord.dbd (+25/-0) src/rec/aaoRecord.c (+102/-49) src/rec/aaoRecord.dbd (+25/-0) |
To merge this branch: | bzr merge lp:~dirk.zimoch/epics-base/fix-aai-and-aao |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Johnson | Approve | ||
Review via email: mp+26195@code.launchpad.net |
This proposal supersedes a proposal from 2010-05-27.
Commit message
Description of the change
* Bugfix: writing to aai/aao via db link crashed ioc. Memory allocation / device support init_record moved to pass 0.
* Soft device support for aai and aao added.
* Simulation mode fixed. SIOL link added. (sim handling is done in devsup!)
* Bugfix: writing to aai/aao modified NELM. Modify NORD instead.
* Hashing added to minimize monitor updates (like in waveform record)
Discussion:
Add features like RVAL->VAL conversion, scaling, smoothing, alarm limits?
Ralph Lange (ralph-lange) wrote : Posted in a previous version of this proposal | # |
Andrew Johnson (anj) wrote : | # |
Hi Dirk,
When SIMM=YES, the aai record is put into alarm using the SIMS field for the severity. The aao record always goes to INVALID_ALARM in simulation mode.
Do you know under what circumstances a device support might want to set BPTR itself? The comment about calling the pdset->
Have you ever seen any written documentation for the aai/aao record types? There are no chapters for them in the Record Reference wiki yet.
I haven't started actually testing this code yet (that's my next task), but so far I think this work should be merged into R3.14.12.
- Andrew
Ben Franksen (bfrk) wrote : | # |
On Freitag, 2. Juli 2010, Andrew Johnson wrote:
> Do you know under what circumstances a device support might want to set
> BPTR itself?
Slightly off-topic, but I suggest removing BPTR and use VAL field instead.
VAL is not used for anything at the moment, AFAIR, and is also
DBF_NOACCESS, so this is even compatible (but not for device support, maybe
this is the reason this hasn't been done before?).
Same for waveform record, BTW.
Cheers
Ben
Andrew Johnson (anj) wrote : | # |
Hi Ben,
Interesting point, although not relevant to the review of this particular branch. Making that change to the records would require a corresponding modification to all device supports, so it's not something I'd want to do for 3.14.12. I guess removing the BPTR fields completely would cause any unmodified code to fail at compile-time (which is what we'd want), so it's not an impossible idea for 3.15.
Thanks,
- Andrew
Dirk Zimoch (dirk.zimoch) wrote : | # |
Andrew,
> The aao record always goes to INVALID_ALARM in simulation mode.
I missed that. It should use the SIMS field as well. As soon as I get bazaar installed on this computer, I will fix that.
I have never seen documentation on the aai/aao records, but I guess that the intention was to set BPTR directly to memory mapped register space to save the time for copying data. But this has several disadvantages:
* BPTR must be set early enough (fixed now)
* BPTR must not change at run time (e.g. no double buffering). I have to check what devExtend() does to solve this problem.
* As a result, BPTR may contain inconsistent data if the hardware modifies the buffer while it is being read (e.g. by a CA read or monitor)
I kept the memory allocation model to stay compatible to old device supports. Additionally I allow for new device supports not to set BPTR. Also to stay compatible, I do not want to switch from BPTR to VAL.
Basically the aai is the same as the waveform record except that it does not have a RARM field. The aao is the only record that is intended to write arrays. (The waveform can write through its INP if the device support allows. But if we do so, why do we need ai/ao, mbbi/mbbo, etc. pairs?)
Andrew Johnson (anj) wrote : | # |
On Monday 05 July 2010 03:02:23 Dirk Zimoch wrote:
>
> * BPTR must not change at run time (e.g. no double buffering). I have to
> check what devExtend() does to solve this problem.
Sorry, devExtend() is the way that a device support tells the iocCore code
that it can accept address changes at runtime; it doesn't solve that problem.
The devExtend() routine must be called from a dset->init() routine and points
to a dsxt structure with the add_record() and del_record() routines that
support those runtime changes for this device support. My point was merely
that if BPTR can't be changed after rset->init_
because this somehow stops DB links from working] that it's not going to be
possible to have extended device support that sets BPTR. Not a major issue,
and there are no incompatibilities here.
> I kept the memory allocation model to stay compatible to old device
> supports. Additionally I allow for new device supports not to set BPTR.
> Also to stay compatible, I do not want to switch from BPTR to VAL.
I agree that this is the best solution for now.
Thanks,
- Andrew
--
The best FOSS code is written to be read by other humans -- Harald Welte
Dirk Zimoch (dirk.zimoch) wrote : | # |
What we really need to make this work as intended, i.e. modify BPTR at run-time to point to the current data, is a way to tell a link, a CA connection, and maybe other EPICS components that the address of the data has changed. But this is a completely different problem.
Andrew Johnson (anj) wrote : | # |
Asynchronous processing doesn't work because of the line
if (pact) return 0;
in the process() routines of both record types.
With those lines removed I'm happy with the result, so I will merge the code.
Thanks,
- Andrew
Preview Diff
1 | === modified file 'documentation/RELEASE_NOTES.html' |
2 | --- documentation/RELEASE_NOTES.html 2010-07-01 16:59:22 +0000 |
3 | +++ documentation/RELEASE_NOTES.html 2010-07-07 17:48:44 +0000 |
4 | @@ -11,6 +11,13 @@ |
5 | |
6 | <h2 align="center">Changes between 3.14.11 and 3.14.12</h2> |
7 | <!-- Insert new items immediately below here ... --> |
8 | +<h4>Record Types aai and aao</h4> |
9 | +<p>Fixed bug in memory allocation that caused crashes when linking other records |
10 | +to aai or aao. |
11 | +Fixed bug where NELM was modified instead of NORD. |
12 | +Added Soft Channel device support. |
13 | +Added SIOL link and proper simulation mode for Soft Channel support. |
14 | +Added MPST, APST and HASH fields for monitor on change support like in waveform record. |
15 | |
16 | |
17 | <h4>devLib cleanup</h4> |
18 | |
19 | === modified file 'src/dev/softDev/Makefile' |
20 | --- src/dev/softDev/Makefile 2008-09-24 22:40:37 +0000 |
21 | +++ src/dev/softDev/Makefile 2010-07-07 17:48:44 +0000 |
22 | @@ -12,6 +12,8 @@ |
23 | |
24 | DBD += devSoft.dbd |
25 | |
26 | +LIBSRCS += devAaiSoft.c |
27 | +LIBSRCS += devAaoSoft.c |
28 | LIBSRCS += devAiSoft.c |
29 | LIBSRCS += devAiSoftRaw.c |
30 | LIBSRCS += devAoSoft.c |
31 | |
32 | === added file 'src/dev/softDev/devAaiSoft.c' |
33 | --- src/dev/softDev/devAaiSoft.c 1970-01-01 00:00:00 +0000 |
34 | +++ src/dev/softDev/devAaiSoft.c 2010-07-07 17:48:44 +0000 |
35 | @@ -0,0 +1,87 @@ |
36 | +/*************************************************************************\ |
37 | +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne |
38 | +* National Laboratory. |
39 | +* Copyright (c) 2002 The Regents of the University of California, as |
40 | +* Operator of Los Alamos National Laboratory. |
41 | +* EPICS BASE is distributed subject to a Software License Agreement found |
42 | +* in file LICENSE that is included with this distribution. |
43 | +\*************************************************************************/ |
44 | + |
45 | +/* $Id$ |
46 | + * devAaiSoft.c - Device Support Routines for soft Waveform Records |
47 | + * |
48 | + * Original Author: Bob Dalesio |
49 | + * Current Author: Dirk Zimoch |
50 | + * Date: 27-MAY-2010 |
51 | + */ |
52 | + |
53 | +#include <stdlib.h> |
54 | +#include <stdio.h> |
55 | +#include <string.h> |
56 | + |
57 | +#include "alarm.h" |
58 | +#include "dbDefs.h" |
59 | +#include "dbAccess.h" |
60 | +#include "recGbl.h" |
61 | +#include "devSup.h" |
62 | +#include "cantProceed.h" |
63 | +#include "menuYesNo.h" |
64 | +#include "aaiRecord.h" |
65 | +#include "epicsExport.h" |
66 | + |
67 | +/* Create the dset for devAaiSoft */ |
68 | +static long init_record(); |
69 | +static long read_aai(); |
70 | + |
71 | +struct { |
72 | + long number; |
73 | + DEVSUPFUN report; |
74 | + DEVSUPFUN init; |
75 | + DEVSUPFUN init_record; |
76 | + DEVSUPFUN get_ioint_info; |
77 | + DEVSUPFUN read_aai; |
78 | +} devAaiSoft = { |
79 | + 5, |
80 | + NULL, |
81 | + NULL, |
82 | + init_record, |
83 | + NULL, |
84 | + read_aai |
85 | +}; |
86 | +epicsExportAddress(dset,devAaiSoft); |
87 | + |
88 | +static long init_record(aaiRecord *prec) |
89 | +{ |
90 | + /* INP must be a CONSTANT or a PV_LINK or a DB_LINK or a CA_LINK*/ |
91 | + switch (prec->inp.type) { |
92 | + case CONSTANT: |
93 | + prec->nord = 0; |
94 | + break; |
95 | + case PV_LINK: |
96 | + case DB_LINK: |
97 | + case CA_LINK: |
98 | + break; |
99 | + default : |
100 | + recGblRecordError(S_db_badField, (void *)prec, |
101 | + "devAaiSoft (init_record) Illegal INP field"); |
102 | + return(S_db_badField); |
103 | + } |
104 | + return 0; |
105 | +} |
106 | + |
107 | +static long read_aai(aaiRecord *prec) |
108 | +{ |
109 | + long nRequest = prec->nelm; |
110 | + |
111 | + dbGetLink(prec->simm == menuYesNoYES ? &prec->siol : &prec->inp, |
112 | + prec->ftvl, prec->bptr, 0, &nRequest); |
113 | + if (nRequest > 0) { |
114 | + prec->nord = nRequest; |
115 | + prec->udf=FALSE; |
116 | + if (prec->tsel.type == CONSTANT && |
117 | + prec->tse == epicsTimeEventDeviceTime) |
118 | + dbGetTimeStamp(&prec->inp, &prec->time); |
119 | + } |
120 | + |
121 | + return 0; |
122 | +} |
123 | |
124 | === added file 'src/dev/softDev/devAaoSoft.c' |
125 | --- src/dev/softDev/devAaoSoft.c 1970-01-01 00:00:00 +0000 |
126 | +++ src/dev/softDev/devAaoSoft.c 2010-07-07 17:48:44 +0000 |
127 | @@ -0,0 +1,79 @@ |
128 | +/*************************************************************************\ |
129 | +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne |
130 | +* National Laboratory. |
131 | +* Copyright (c) 2002 The Regents of the University of California, as |
132 | +* Operator of Los Alamos National Laboratory. |
133 | +* EPICS BASE is distributed subject to a Software License Agreement found |
134 | +* in file LICENSE that is included with this distribution. |
135 | +\*************************************************************************/ |
136 | + |
137 | +/* $Id$ |
138 | + * devAaoSoft.c - Device Support Routines for soft Waveform Records |
139 | + * |
140 | + * Original Author: Bob Dalesio |
141 | + * Current Author: Dirk Zimoch |
142 | + * Date: 27-MAY-2010 |
143 | + */ |
144 | + |
145 | +#include <stdlib.h> |
146 | +#include <stdio.h> |
147 | +#include <string.h> |
148 | + |
149 | +#include "alarm.h" |
150 | +#include "dbDefs.h" |
151 | +#include "dbAccess.h" |
152 | +#include "recGbl.h" |
153 | +#include "devSup.h" |
154 | +#include "cantProceed.h" |
155 | +#include "menuYesNo.h" |
156 | +#include "aaoRecord.h" |
157 | +#include "epicsExport.h" |
158 | + |
159 | +/* Create the dset for devAaoSoft */ |
160 | +static long init_record(); |
161 | +static long write_aao(); |
162 | + |
163 | +struct { |
164 | + long number; |
165 | + DEVSUPFUN report; |
166 | + DEVSUPFUN init; |
167 | + DEVSUPFUN init_record; |
168 | + DEVSUPFUN get_ioint_info; |
169 | + DEVSUPFUN read_aao; |
170 | +} devAaoSoft = { |
171 | + 5, |
172 | + NULL, |
173 | + NULL, |
174 | + init_record, |
175 | + NULL, |
176 | + write_aao |
177 | +}; |
178 | +epicsExportAddress(dset,devAaoSoft); |
179 | + |
180 | +static long init_record(aaoRecord *prec) |
181 | +{ |
182 | + /* OUT must be a CONSTANT or a PV_LINK or a DB_LINK or a CA_LINK*/ |
183 | + switch (prec->out.type) { |
184 | + case CONSTANT: |
185 | + prec->nord = 0; |
186 | + break; |
187 | + case PV_LINK: |
188 | + case DB_LINK: |
189 | + case CA_LINK: |
190 | + break; |
191 | + default : |
192 | + recGblRecordError(S_db_badField, prec, |
193 | + "devAaoSoft (init_record) Illegal OUT field"); |
194 | + return(S_db_badField); |
195 | + } |
196 | + return 0; |
197 | +} |
198 | + |
199 | +static long write_aao(aaoRecord *prec) |
200 | +{ |
201 | + long nRequest = prec->nord; |
202 | + dbPutLink(prec->simm == menuYesNoYES ? &prec->siol : &prec->out, |
203 | + prec->ftvl, prec->bptr, nRequest); |
204 | + |
205 | + return 0; |
206 | +} |
207 | |
208 | === modified file 'src/dev/softDev/devSoft.dbd' |
209 | --- src/dev/softDev/devSoft.dbd 2008-09-24 22:40:37 +0000 |
210 | +++ src/dev/softDev/devSoft.dbd 2010-07-07 17:48:44 +0000 |
211 | @@ -1,3 +1,5 @@ |
212 | +device(aai,CONSTANT,devAaiSoft,"Soft Channel") |
213 | +device(aao,CONSTANT,devAaoSoft,"Soft Channel") |
214 | device(ai,CONSTANT,devAiSoft,"Soft Channel") |
215 | device(ao,CONSTANT,devAoSoft,"Soft Channel") |
216 | device(bi,CONSTANT,devBiSoft,"Soft Channel") |
217 | |
218 | === modified file 'src/misc/base.dbd' |
219 | --- src/misc/base.dbd 2008-08-14 20:41:05 +0000 |
220 | +++ src/misc/base.dbd 2010-07-07 17:48:44 +0000 |
221 | @@ -8,6 +8,8 @@ |
222 | include "menuConvert.dbd" |
223 | |
224 | # Record types |
225 | +include "aaiRecord.dbd" |
226 | +include "aaoRecord.dbd" |
227 | include "aiRecord.dbd" |
228 | include "aoRecord.dbd" |
229 | include "aSubRecord.dbd" |
230 | |
231 | === modified file 'src/rec/aaiRecord.c' |
232 | --- src/rec/aaiRecord.c 2009-07-08 18:14:11 +0000 |
233 | +++ src/rec/aaiRecord.c 2010-07-07 17:48:44 +0000 |
234 | @@ -9,7 +9,6 @@ |
235 | /* recAai.c - Record Support Routines for Array Analog In records */ |
236 | /* |
237 | * Original Author: Dave Barker |
238 | - * Date: 10/24/93 |
239 | * |
240 | * C E B A F |
241 | * |
242 | @@ -18,6 +17,8 @@ |
243 | * |
244 | * Copyright SURA CEBAF 1993. |
245 | * |
246 | + * Current Author: Dirk Zimoch <dirk.zimoch@psi.ch> |
247 | + * Date: 27-MAY-2010 |
248 | */ |
249 | |
250 | #include <stddef.h> |
251 | @@ -28,14 +29,17 @@ |
252 | |
253 | #include "dbDefs.h" |
254 | #include "epicsPrint.h" |
255 | +#include "epicsString.h" |
256 | #include "alarm.h" |
257 | #include "dbAccess.h" |
258 | +#include "dbEvent.h" |
259 | +#include "dbFldTypes.h" |
260 | #include "dbScan.h" |
261 | -#include "dbEvent.h" |
262 | #include "devSup.h" |
263 | #include "errMdef.h" |
264 | #include "recSup.h" |
265 | #include "recGbl.h" |
266 | +#include "cantProceed.h" |
267 | #include "menuYesNo.h" |
268 | #define GEN_SIZE_OFFSET |
269 | #include "aaiRecord.h" |
270 | @@ -48,7 +52,7 @@ |
271 | static long init_record(aaiRecord *, int); |
272 | static long process(aaiRecord *); |
273 | #define special NULL |
274 | -static long get_value(aaiRecord *, struct valueDes *); |
275 | +#define get_value NULL |
276 | static long cvt_dbaddr(DBADDR *); |
277 | static long get_array_info(DBADDR *, long *, long *); |
278 | static long put_array_info(DBADDR *, long); |
279 | @@ -84,43 +88,67 @@ |
280 | epicsExportAddress(rset,aaiRSET); |
281 | |
282 | struct aaidset { /* aai dset */ |
283 | - long number; |
284 | - DEVSUPFUN dev_report; |
285 | - DEVSUPFUN init; |
286 | - DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/ |
287 | - DEVSUPFUN get_ioint_info; |
288 | - DEVSUPFUN read_aai; /*returns: (-1,0)=>(failure,success)*/ |
289 | + long number; |
290 | + DEVSUPFUN dev_report; |
291 | + DEVSUPFUN init; |
292 | + DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/ |
293 | + DEVSUPFUN get_ioint_info; |
294 | + DEVSUPFUN read_aai; /*returns: (-1,0)=>(failure,success)*/ |
295 | }; |
296 | |
297 | static void monitor(aaiRecord *); |
298 | static long readValue(aaiRecord *); |
299 | |
300 | - |
301 | static long init_record(aaiRecord *prec, int pass) |
302 | { |
303 | - struct aaidset *pdset; |
304 | long status; |
305 | + struct aaidset *pdset = (struct aaidset *)(prec->dset); |
306 | |
307 | + /* must have dset defined */ |
308 | + if (!pdset) { |
309 | + recGblRecordError(S_dev_noDSET, prec, "aai: init_record"); |
310 | + return S_dev_noDSET; |
311 | + } |
312 | + |
313 | if (pass == 0) { |
314 | - if (prec->nelm <= 0) prec->nelm = 1; |
315 | + if (prec->nelm <= 0) |
316 | + prec->nelm = 1; |
317 | + if (prec->ftvl > DBF_ENUM) |
318 | + prec->ftvl = DBF_UCHAR; |
319 | + if (prec->nelm == 1) { |
320 | + prec->nord = 1; |
321 | + } else { |
322 | + prec->nord = 0; |
323 | + } |
324 | + |
325 | + /* we must call pdset->init_record in pass 0 |
326 | + because it may set prec->bptr which must |
327 | + not change after links are established before pass 1 |
328 | + */ |
329 | + |
330 | + if (pdset->init_record) { |
331 | + /* init_record may set the bptr to point to the data */ |
332 | + if ((status = pdset->init_record(prec))) |
333 | + return status; |
334 | + } |
335 | + if (!prec->bptr) { |
336 | + /* device support did not allocate memory so we must do it */ |
337 | + prec->bptr = callocMustSucceed(prec->nelm, dbValueSize(prec->ftvl), |
338 | + "aai: buffer calloc failed"); |
339 | + } |
340 | return 0; |
341 | } |
342 | - recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm); |
343 | - /* must have dset defined */ |
344 | - if (!(pdset = (struct aaidset *)(prec->dset))) { |
345 | - recGblRecordError(S_dev_noDSET, (void *)prec, "aai: init_record"); |
346 | - return S_dev_noDSET; |
347 | + |
348 | + /* SIML must be a CONSTANT or a PV_LINK or a DB_LINK */ |
349 | + if (prec->siml.type == CONSTANT) { |
350 | + recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm); |
351 | } |
352 | + |
353 | /* must have read_aai function defined */ |
354 | if (pdset->number < 5 || pdset->read_aai == NULL) { |
355 | - recGblRecordError(S_dev_missingSup, (void *)prec, "aai: init_record"); |
356 | + recGblRecordError(S_dev_missingSup, prec, "aai: init_record"); |
357 | return S_dev_missingSup; |
358 | } |
359 | - if (pdset->init_record) { |
360 | - /* init_record sets the bptr to point to the data */ |
361 | - if ((status = pdset->init_record(prec))) |
362 | - return status; |
363 | - } |
364 | return 0; |
365 | } |
366 | |
367 | @@ -132,14 +160,13 @@ |
368 | |
369 | if (pdset == NULL || pdset->read_aai == NULL) { |
370 | prec->pact = TRUE; |
371 | - recGblRecordError(S_dev_missingSup, (void *)prec, "read_aai"); |
372 | + recGblRecordError(S_dev_missingSup, prec, "read_aai"); |
373 | return S_dev_missingSup; |
374 | } |
375 | |
376 | if (pact) return 0; |
377 | |
378 | status = readValue(prec); /* read the new value */ |
379 | - /* check if device support set pact */ |
380 | if (!pact && prec->pact) return 0; |
381 | prec->pact = TRUE; |
382 | |
383 | @@ -151,22 +178,14 @@ |
384 | recGblFwdLink(prec); |
385 | |
386 | prec->pact = FALSE; |
387 | - return 0; |
388 | -} |
389 | - |
390 | -static long get_value(aaiRecord *prec, struct valueDes *pvdes) |
391 | -{ |
392 | - pvdes->no_elements = prec->nelm; |
393 | - pvdes->pvalue = prec->bptr; |
394 | - pvdes->field_type = prec->ftvl; |
395 | - return 0; |
396 | + return status; |
397 | } |
398 | |
399 | static long cvt_dbaddr(DBADDR *paddr) |
400 | { |
401 | aaiRecord *prec = (aaiRecord *)paddr->precord; |
402 | |
403 | - paddr->pfield = (void *)(prec->bptr); |
404 | + paddr->pfield = prec->bptr; |
405 | paddr->no_elements = prec->nelm; |
406 | paddr->field_type = prec->ftvl; |
407 | paddr->field_size = dbValueSize(prec->ftvl); |
408 | @@ -178,7 +197,7 @@ |
409 | { |
410 | aaiRecord *prec = (aaiRecord *)paddr->precord; |
411 | |
412 | - *no_elements = prec->nelm; |
413 | + *no_elements = prec->nord; |
414 | *offset = 0; |
415 | return 0; |
416 | } |
417 | @@ -187,7 +206,9 @@ |
418 | { |
419 | aaiRecord *prec = (aaiRecord *)paddr->precord; |
420 | |
421 | - prec->nelm = nNew; |
422 | + prec->nord = nNew; |
423 | + if (prec->nord > prec->nelm) |
424 | + prec->nord = prec->nelm; |
425 | return 0; |
426 | } |
427 | |
428 | @@ -204,7 +225,7 @@ |
429 | aaiRecord *prec = (aaiRecord *)paddr->precord; |
430 | |
431 | *precision = prec->prec; |
432 | - if (paddr->pfield == (void *)prec->bptr) return 0; |
433 | + if (paddr->pfield == prec->bptr) return 0; |
434 | recGblGetPrec(paddr, precision); |
435 | return 0; |
436 | } |
437 | @@ -213,7 +234,7 @@ |
438 | { |
439 | aaiRecord *prec = (aaiRecord *)paddr->precord; |
440 | |
441 | - if (paddr->pfield == (void *)prec->bptr) { |
442 | + if (paddr->pfield == prec->bptr) { |
443 | pgd->upper_disp_limit = prec->hopr; |
444 | pgd->lower_disp_limit = prec->lopr; |
445 | } else recGblGetGraphicDouble(paddr, pgd); |
446 | @@ -224,7 +245,7 @@ |
447 | { |
448 | aaiRecord *prec = (aaiRecord *)paddr->precord; |
449 | |
450 | - if (paddr->pfield == (void *)prec->bptr) { |
451 | + if (paddr->pfield == prec->bptr) { |
452 | pcd->upper_ctrl_limit = prec->hopr; |
453 | pcd->lower_ctrl_limit = prec->lopr; |
454 | } else recGblGetControlDouble(paddr, pcd); |
455 | @@ -234,9 +255,35 @@ |
456 | static void monitor(aaiRecord *prec) |
457 | { |
458 | unsigned short monitor_mask; |
459 | + unsigned int hash = 0; |
460 | |
461 | monitor_mask = recGblResetAlarms(prec); |
462 | - monitor_mask |= (DBE_LOG | DBE_VALUE); |
463 | + |
464 | + if (prec->mpst == aaiPOST_Always) |
465 | + monitor_mask |= DBE_VALUE; |
466 | + if (prec->apst == aaiPOST_Always) |
467 | + monitor_mask |= DBE_LOG; |
468 | + |
469 | + /* Calculate hash if we are interested in OnChange events. */ |
470 | + if ((prec->mpst == aaiPOST_OnChange) || |
471 | + (prec->apst == aaiPOST_OnChange)) { |
472 | + hash = epicsMemHash(prec->bptr, |
473 | + prec->nord * dbValueSize(prec->ftvl), 0); |
474 | + |
475 | + /* Only post OnChange values if the hash is different. */ |
476 | + if (hash != prec->hash) { |
477 | + if (prec->mpst == aaiPOST_OnChange) |
478 | + monitor_mask |= DBE_VALUE; |
479 | + if (prec->apst == aaiPOST_OnChange) |
480 | + monitor_mask |= DBE_LOG; |
481 | + |
482 | + /* Store hash for next process. */ |
483 | + prec->hash = hash; |
484 | + /* Post HASH. */ |
485 | + db_post_events(prec, &prec->hash, DBE_VALUE); |
486 | + } |
487 | + } |
488 | + |
489 | if (monitor_mask) |
490 | db_post_events(prec, prec->bptr, monitor_mask); |
491 | } |
492 | @@ -253,21 +300,25 @@ |
493 | |
494 | status = dbGetLink(&prec->siml, DBR_ENUM, &prec->simm, 0, 0); |
495 | if (status) |
496 | - return(status); |
497 | + return status; |
498 | |
499 | if (prec->simm == menuYesNoNO){ |
500 | - /* Call dev support */ |
501 | - status = pdset->read_aai(prec); |
502 | - return status; |
503 | + return pdset->read_aai(prec); |
504 | } |
505 | + |
506 | if (prec->simm == menuYesNoYES){ |
507 | - /* Simm processing split performed in devSup */ |
508 | - /* Call dev support */ |
509 | - status = pdset->read_aai(prec); |
510 | - return status; |
511 | + /* Device suport is responsible for buffer |
512 | + which might be read-only so we may not be |
513 | + allowed to call dbGetLink on it. |
514 | + Maybe also device support has an advanced |
515 | + simulation mode. |
516 | + Thus call device now. |
517 | + */ |
518 | + recGblSetSevr(prec, SIMM_ALARM, prec->sims); |
519 | + return pdset->read_aai(prec); |
520 | } |
521 | - status = -1; |
522 | - recGblSetSevr(prec, SIMM_ALARM, INVALID_ALARM); |
523 | - return status; |
524 | + |
525 | + recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); |
526 | + return -1; |
527 | } |
528 | |
529 | |
530 | === modified file 'src/rec/aaiRecord.dbd' |
531 | --- src/rec/aaiRecord.dbd 2002-07-12 21:35:43 +0000 |
532 | +++ src/rec/aaiRecord.dbd 2010-07-07 17:48:44 +0000 |
533 | @@ -7,6 +7,10 @@ |
534 | # and higher are distributed subject to a Software License Agreement found |
535 | # in file LICENSE that is included with this distribution. |
536 | #************************************************************************* |
537 | +menu(aaiPOST) { |
538 | + choice(aaiPOST_Always,"Always") |
539 | + choice(aaiPOST_OnChange,"On Change") |
540 | +} |
541 | recordtype(aai) { |
542 | include "dbCommon.dbd" |
543 | field(VAL,DBF_NOACCESS) { |
544 | @@ -82,4 +86,25 @@ |
545 | interest(2) |
546 | menu(menuAlarmSevr) |
547 | } |
548 | + field(SIOL,DBF_INLINK) { |
549 | + prompt("Sim Input Specifctn") |
550 | + promptgroup(GUI_INPUTS) |
551 | + interest(1) |
552 | + } |
553 | + field(MPST,DBF_MENU) { |
554 | + prompt("Post Value Monitors") |
555 | + promptgroup(GUI_DISPLAY) |
556 | + interest(1) |
557 | + menu(aaiPOST) |
558 | + } |
559 | + field(APST,DBF_MENU) { |
560 | + prompt("Post Archive Monitors") |
561 | + promptgroup(GUI_DISPLAY) |
562 | + interest(1) |
563 | + menu(aaiPOST) |
564 | + } |
565 | + field(HASH,DBF_ULONG) { |
566 | + prompt("Hash of OnChange data.") |
567 | + interest(3) |
568 | + } |
569 | } |
570 | |
571 | === modified file 'src/rec/aaoRecord.c' |
572 | --- src/rec/aaoRecord.c 2009-07-08 18:14:11 +0000 |
573 | +++ src/rec/aaoRecord.c 2010-07-07 17:48:44 +0000 |
574 | @@ -9,7 +9,6 @@ |
575 | /* recAao.c - Record Support Routines for Array Analog Out records */ |
576 | /* |
577 | * Original Author: Dave Barker |
578 | - * Date: 10/28/93 |
579 | * |
580 | * C E B A F |
581 | * |
582 | @@ -18,6 +17,8 @@ |
583 | * |
584 | * Copyright SURA CEBAF 1993. |
585 | * |
586 | + * Current Author: Dirk Zimoch <dirk.zimoch@psi.ch> |
587 | + * Date: 27-MAY-2010 |
588 | */ |
589 | |
590 | #include <stddef.h> |
591 | @@ -28,14 +29,17 @@ |
592 | |
593 | #include "dbDefs.h" |
594 | #include "epicsPrint.h" |
595 | +#include "epicsString.h" |
596 | #include "alarm.h" |
597 | #include "dbAccess.h" |
598 | +#include "dbEvent.h" |
599 | #include "dbFldTypes.h" |
600 | #include "dbScan.h" |
601 | -#include "dbEvent.h" |
602 | #include "devSup.h" |
603 | +#include "errMdef.h" |
604 | #include "recSup.h" |
605 | #include "recGbl.h" |
606 | +#include "cantProceed.h" |
607 | #include "menuYesNo.h" |
608 | #define GEN_SIZE_OFFSET |
609 | #include "aaoRecord.h" |
610 | @@ -48,7 +52,7 @@ |
611 | static long init_record(aaoRecord *, int); |
612 | static long process(aaoRecord *); |
613 | #define special NULL |
614 | -static long get_value(aaoRecord *, struct valueDes *); |
615 | +#define get_value NULL |
616 | static long cvt_dbaddr(DBADDR *); |
617 | static long get_array_info(DBADDR *, long *, long *); |
618 | static long put_array_info(DBADDR *, long); |
619 | @@ -84,43 +88,67 @@ |
620 | epicsExportAddress(rset,aaoRSET); |
621 | |
622 | struct aaodset { /* aao dset */ |
623 | - long number; |
624 | - DEVSUPFUN dev_report; |
625 | - DEVSUPFUN init; |
626 | - DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/ |
627 | - DEVSUPFUN get_ioint_info; |
628 | - DEVSUPFUN write_aao; /*returns: (-1,0)=>(failure,success)*/ |
629 | + long number; |
630 | + DEVSUPFUN dev_report; |
631 | + DEVSUPFUN init; |
632 | + DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/ |
633 | + DEVSUPFUN get_ioint_info; |
634 | + DEVSUPFUN write_aao; /*returns: (-1,0)=>(failure,success)*/ |
635 | }; |
636 | |
637 | static void monitor(aaoRecord *); |
638 | static long writeValue(aaoRecord *); |
639 | |
640 | - |
641 | static long init_record(aaoRecord *prec, int pass) |
642 | { |
643 | - struct aaodset *pdset; |
644 | long status; |
645 | + struct aaodset *pdset = (struct aaodset *)(prec->dset); |
646 | |
647 | - if (pass == 0) { |
648 | - if (prec->nelm <= 0) prec->nelm = 1; |
649 | - return 0; |
650 | - } |
651 | - recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm); |
652 | /* must have dset defined */ |
653 | - if (!(pdset = (struct aaodset *)(prec->dset))) { |
654 | - recGblRecordError(S_dev_noDSET, (void *)prec, "aao: init_record"); |
655 | + if (!pdset) { |
656 | + recGblRecordError(S_dev_noDSET, prec, "aao: init_record"); |
657 | return S_dev_noDSET; |
658 | } |
659 | + |
660 | + if (pass == 0) { |
661 | + if (prec->nelm <= 0) |
662 | + prec->nelm = 1; |
663 | + if (prec->ftvl > DBF_ENUM) |
664 | + prec->ftvl = DBF_UCHAR; |
665 | + if (prec->nelm == 1) { |
666 | + prec->nord = 1; |
667 | + } else { |
668 | + prec->nord = 0; |
669 | + } |
670 | + |
671 | + /* we must call pdset->init_record in pass 0 |
672 | + because it may set prec->bptr which must |
673 | + not change after links are established before pass 1 |
674 | + */ |
675 | + |
676 | + if (pdset->init_record) { |
677 | + /* init_record may set the bptr to point to the data */ |
678 | + if ((status = pdset->init_record(prec))) |
679 | + return status; |
680 | + } |
681 | + if (!prec->bptr) { |
682 | + /* device support did not allocate memory so we must do it */ |
683 | + prec->bptr = callocMustSucceed(prec->nelm, dbValueSize(prec->ftvl), |
684 | + "aao: buffer calloc failed"); |
685 | + } |
686 | + return 0; |
687 | + } |
688 | + |
689 | + /* SIML must be a CONSTANT or a PV_LINK or a DB_LINK */ |
690 | + if (prec->siml.type == CONSTANT) { |
691 | + recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm); |
692 | + } |
693 | + |
694 | /* must have write_aao function defined */ |
695 | if (pdset->number < 5 || pdset->write_aao == NULL) { |
696 | - recGblRecordError(S_dev_missingSup, (void *)prec, "aao: init_record"); |
697 | + recGblRecordError(S_dev_missingSup, prec, "aao: init_record"); |
698 | return S_dev_missingSup; |
699 | } |
700 | - if (pdset->init_record) { |
701 | - /* init records sets the bptr to point to the data */ |
702 | - if ((status = pdset->init_record(prec))) |
703 | - return status; |
704 | - } |
705 | return 0; |
706 | } |
707 | |
708 | @@ -132,13 +160,15 @@ |
709 | |
710 | if (pdset == NULL || pdset->write_aao == NULL) { |
711 | prec->pact = TRUE; |
712 | - recGblRecordError(S_dev_missingSup, (void *)prec, "write_aao"); |
713 | + recGblRecordError(S_dev_missingSup, prec, "write_aao"); |
714 | return S_dev_missingSup; |
715 | } |
716 | |
717 | if (pact) return 0; |
718 | |
719 | status = writeValue(prec); /* write the data */ |
720 | + if (!pact && prec->pact) return 0; |
721 | + prec->pact = TRUE; |
722 | |
723 | prec->udf = FALSE; |
724 | recGblGetTimeStamp(prec); |
725 | @@ -148,22 +178,14 @@ |
726 | recGblFwdLink(prec); |
727 | |
728 | prec->pact = FALSE; |
729 | - return 0; |
730 | -} |
731 | - |
732 | -static long get_value(aaoRecord *prec, struct valueDes *pvdes) |
733 | -{ |
734 | - pvdes->no_elements = prec->nelm; |
735 | - pvdes->pvalue = prec->bptr; |
736 | - pvdes->field_type = prec->ftvl; |
737 | - return 0; |
738 | + return status; |
739 | } |
740 | |
741 | static long cvt_dbaddr(DBADDR *paddr) |
742 | { |
743 | aaoRecord *prec = (aaoRecord *)paddr->precord; |
744 | |
745 | - paddr->pfield = (void *)(prec->bptr); |
746 | + paddr->pfield = prec->bptr; |
747 | paddr->no_elements = prec->nelm; |
748 | paddr->field_type = prec->ftvl; |
749 | paddr->field_size = dbValueSize(prec->ftvl); |
750 | @@ -175,7 +197,7 @@ |
751 | { |
752 | aaoRecord *prec = (aaoRecord *)paddr->precord; |
753 | |
754 | - *no_elements = prec->nelm; |
755 | + *no_elements = prec->nord; |
756 | *offset = 0; |
757 | return 0; |
758 | } |
759 | @@ -184,7 +206,9 @@ |
760 | { |
761 | aaoRecord *prec = (aaoRecord *)paddr->precord; |
762 | |
763 | - prec->nelm = nNew; |
764 | + prec->nord = nNew; |
765 | + if (prec->nord > prec->nelm) |
766 | + prec->nord = prec->nelm; |
767 | return 0; |
768 | } |
769 | |
770 | @@ -210,7 +234,7 @@ |
771 | { |
772 | aaoRecord *prec = (aaoRecord *)paddr->precord; |
773 | |
774 | - if (paddr->pfield == (void *)prec->bptr) { |
775 | + if (paddr->pfield == prec->bptr) { |
776 | pgd->upper_disp_limit = prec->hopr; |
777 | pgd->lower_disp_limit = prec->lopr; |
778 | } else recGblGetGraphicDouble(paddr,pgd); |
779 | @@ -221,7 +245,7 @@ |
780 | { |
781 | aaoRecord *prec = (aaoRecord *)paddr->precord; |
782 | |
783 | - if(paddr->pfield==(void *)prec->bptr){ |
784 | + if(paddr->pfield == prec->bptr){ |
785 | pcd->upper_ctrl_limit = prec->hopr; |
786 | pcd->lower_ctrl_limit = prec->lopr; |
787 | } else recGblGetControlDouble(paddr,pcd); |
788 | @@ -231,9 +255,35 @@ |
789 | static void monitor(aaoRecord *prec) |
790 | { |
791 | unsigned short monitor_mask; |
792 | + unsigned int hash = 0; |
793 | |
794 | monitor_mask = recGblResetAlarms(prec); |
795 | - monitor_mask |= (DBE_LOG | DBE_VALUE); |
796 | + |
797 | + if (prec->mpst == aaoPOST_Always) |
798 | + monitor_mask |= DBE_VALUE; |
799 | + if (prec->apst == aaoPOST_Always) |
800 | + monitor_mask |= DBE_LOG; |
801 | + |
802 | + /* Calculate hash if we are interested in OnChange events. */ |
803 | + if ((prec->mpst == aaoPOST_OnChange) || |
804 | + (prec->apst == aaoPOST_OnChange)) { |
805 | + hash = epicsMemHash(prec->bptr, |
806 | + prec->nord * dbValueSize(prec->ftvl), 0); |
807 | + |
808 | + /* Only post OnChange values if the hash is different. */ |
809 | + if (hash != prec->hash) { |
810 | + if (prec->mpst == aaoPOST_OnChange) |
811 | + monitor_mask |= DBE_VALUE; |
812 | + if (prec->apst == aaoPOST_OnChange) |
813 | + monitor_mask |= DBE_LOG; |
814 | + |
815 | + /* Store hash for next process. */ |
816 | + prec->hash = hash; |
817 | + /* Post HASH. */ |
818 | + db_post_events(prec, &prec->hash, DBE_VALUE); |
819 | + } |
820 | + } |
821 | + |
822 | if (monitor_mask) |
823 | db_post_events(prec, prec->bptr, monitor_mask); |
824 | } |
825 | @@ -253,17 +303,20 @@ |
826 | return status; |
827 | |
828 | if (prec->simm == menuYesNoNO) { |
829 | - /* Call dev support */ |
830 | - status = pdset->write_aao(prec); |
831 | - return status; |
832 | + return pdset->write_aao(prec); |
833 | } |
834 | if (prec->simm == menuYesNoYES) { |
835 | - /* Call dev support */ |
836 | - status = pdset->write_aao(prec); |
837 | - return status; |
838 | + /* Device suport is responsible for buffer |
839 | + which might be write-only so we may not be |
840 | + allowed to call dbPutLink on it. |
841 | + Maybe also device support has an advanced |
842 | + simulation mode. |
843 | + Thus call device now. |
844 | + */ |
845 | + recGblSetSevr(prec, SIMM_ALARM, prec->sims); |
846 | + return pdset->write_aao(prec); |
847 | } |
848 | - status = -1; |
849 | - recGblSetSevr(prec, SIMM_ALARM, INVALID_ALARM); |
850 | - return status; |
851 | + recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); |
852 | + return -1; |
853 | } |
854 | |
855 | |
856 | === modified file 'src/rec/aaoRecord.dbd' |
857 | --- src/rec/aaoRecord.dbd 2002-07-12 21:35:43 +0000 |
858 | +++ src/rec/aaoRecord.dbd 2010-07-07 17:48:44 +0000 |
859 | @@ -7,6 +7,10 @@ |
860 | # and higher are distributed subject to a Software License Agreement found |
861 | # in file LICENSE that is included with this distribution. |
862 | #************************************************************************* |
863 | +menu(aaoPOST) { |
864 | + choice(aaoPOST_Always,"Always") |
865 | + choice(aaoPOST_OnChange,"On Change") |
866 | +} |
867 | recordtype(aao) { |
868 | include "dbCommon.dbd" |
869 | field(VAL,DBF_NOACCESS) { |
870 | @@ -82,4 +86,25 @@ |
871 | interest(2) |
872 | menu(menuAlarmSevr) |
873 | } |
874 | + field(SIOL,DBF_OUTLINK) { |
875 | + prompt("Sim Output Specifctn") |
876 | + promptgroup(GUI_INPUTS) |
877 | + interest(1) |
878 | + } |
879 | + field(MPST,DBF_MENU) { |
880 | + prompt("Post Value Monitors") |
881 | + promptgroup(GUI_DISPLAY) |
882 | + interest(1) |
883 | + menu(aaoPOST) |
884 | + } |
885 | + field(APST,DBF_MENU) { |
886 | + prompt("Post Archive Monitors") |
887 | + promptgroup(GUI_DISPLAY) |
888 | + interest(1) |
889 | + menu(aaoPOST) |
890 | + } |
891 | + field(HASH,DBF_ULONG) { |
892 | + prompt("Hash of OnChange data.") |
893 | + interest(3) |
894 | + } |
895 | } |
Looked at the code - the changes look fine to me.
As I never used the aai/aao records, I don't see me being the right person for testing and proper evaluation of the changes in behaviour, though.