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 import xdc.runtime.ILogger;
37 import xdc.runtime.Log;
38 import xdc.rov.ViewInfo;
39
40 /*!
41 * ======== LoggerIdle ========
42 * A logger which routes `Log` events to a users transport function.
43 *
44 * This logger processes log events as they are generated, stores them in
45 * a buffer and during idle sends a section of the buffer to the user's
46 * transport function. If you are seeing no log events or dropping too
47 * many events check that you are not logging too often and have enough idle
48 * time to send. LoggerIdle is compatable with StellarisWare and MWare
49 * devices. Example transports for UART (B92 and F28M35x) and USB (F28M35x)
50 * as well as initialization functions are included in the evmF28M35x.c files
51 * under the device folder in the ti.examples directory.
52 *
53 * @a(Examples)
54 * Configuration example: The following XDC configuration statements
55 * create a logger module, and assign it as the default logger for all
56 * modules.
57 *
58 * @p(code)
59 * var Defaults = xdc.useModule('xdc.runtime.Defaults');
60 * var Diags = xdc.useModule('xdc.runtime.Diags');
61 * var LoggerIdle = xdc.useModule('ti.uia.sysbios.LoggerIdle');
62 *
63 * LoggerIdle.bufferSize = 60;
64 * LoggerIdle.timestamp = false;
65 * LoggerIdle.transportType = LoggerIdle.TransportType_UART;
66 * LoggerIdle.transportFxn = '&LoggerIdle_uartSend';
67 * var LoggerIdleParams = new LoggerIdle.Params();
68 * Defaults.common$.logger = LoggerIdle.create(LoggerIdleParams);
69 * @p
70 */
71
72 @Template("./LoggerIdle.xdt")
73 module LoggerIdle inherits ILogger {
74
75 /*!
76 * ======== TransportType ========
77 * Used to specify the type of transport to use
78 *
79 * This enum is used by the instrumentation host to determine what
80 * the transport is. It is not used by the target code.
81 */
82 enum TransportType {
83 TransportType_UART = 0,
84 TransportType_USB = 1,
85 TransportType_ETHERNET = 2,
86 TransportType_CUSTOM = 3
87 };
88
89 /*!
90 * @_nodoc
91 * ======== ModuleView ========
92 */
93 metaonly struct ModuleView {
94 Bool isEnabled;
95 Bool isTimestampEnabled;
96 Int bufferSize;
97 UInt sequenceNumber;
98 String transportType;
99 String customTransport;
100 }
101
102 metaonly struct RecordView {
103 Int sequence;
104 Long timestampRaw;
105 String modName;
106 String text;
107 Int eventId;
108 String eventName;
109 IArg arg0;
110 IArg arg1;
111 IArg arg2;
112 IArg arg3;
113 IArg arg4;
114 IArg arg5;
115 IArg arg6;
116 IArg arg7;
117 }
118
119 /*!
120 * @_nodoc
121 * ======== rovViewInfo ========
122 */
123 @Facet
124 metaonly config ViewInfo.Instance rovViewInfo =
125 ViewInfo.create({
126 viewMap: [
127 ['Module',
128 {
129 type: ViewInfo.MODULE,
130 viewInitFxn: 'viewInitModule',
131 structName: 'ModuleView'
132 }
133 ],
134 ['Records',
135 {
136 type: xdc.rov.ViewInfo.MODULE_DATA,
137 viewInitFxn: 'viewInitRecords',
138 structName: 'RecordView'
139 }
140 ]
141 ]
142 });
143
144 /*!
145 * ======== RtaData ========
146 * Data added to the RTA MetaData file to support System Analyzer
147 */
148 @XmlDtd metaonly struct RtaData {
149 Int instanceId;
150 }
151
152 /*!
153 * ======== LoggerFxn ========
154 * Typedef for the transport function pointer.
155 */
156 typedef Int (*LoggerFxn)(UChar *, Int);
157
158 /*!
159 * ======== bufferSize ========
160 * LoggerIdle buffer size in 32-bit words.
161 */
162 config SizeT bufferSize = 256;
163
164 /*!
165 * ======== isTimestampEnabled ========
166 * Enable or disable logging the 64b local CPU timestamp
167 * at the start of each event
168 *
169 * Having a timestamp allows an instrumentation host (e.g.
170 * System Analyzer) to display events with the correct system time.
171 */
172 config Bool isTimestampEnabled = true;
173
174 /*!
175 * ======== transportType ========
176 * Transport used to send the records to an instrumentation host
177 *
178 * This parameter is used to specify the transport that the
179 * `{@link #transportFxn}` function will use to send the buffer to
180 * an instrumentation host (e.g. System Analyzer in CCS).
181 *
182 * This parameter is placed into the generated UIA XML file. The
183 * instrumentation host can use the XML file to help it auto-detect as
184 * much as possible and act accordingly.
185 *
186 * If the desired transport is not in the `{@link #TransportType}` enum,
187 * select `{@link #TransportType_CUSTOM}` and set the
188 * `{@link #customTransportType}` string with the desired string.
189 */
190 metaonly config TransportType transportType = TransportType_UART;
191
192 /*!
193 * ======== customTransportType ========
194 * Custom transport used to send the records to an instrumentation host
195 *
196 * If the desired transport is not in the `{@link #TransportType}` enum,
197 * and `{@link #transportType}` is set to `{@link #TransportType_CUSTOM}`,
198 * this parameter must be filled in with the correct transport name.
199 *
200 * If `{@link #transportType}` is NOT set to
201 * `{@link #TransportType_CUSTOM}`, this parameter is ignored.
202 */
203 config String customTransportType = null;
204
205 /*!
206 * ======== transportFxn ========
207 * User defined transport function responsible for transmitting the records
208 */
209 config LoggerFxn transportFxn = null;
210
211 /*!
212 * @_nodoc
213 * ======== writeWhenFull ========
214 *
215 * This configuration parameter has been deprecated. The behavior
216 * is now to always allow wtites when the LoggerIdle buffer is full.
217 *
218 * Allow Log writes to succeed even if the the LoggerIdle buffer is
219 * full.
220 *
221 * LoggerIdle maintains a circular buffer where the Log events are
222 * written. A write pointer indicates the location in the buffer
223 * where the next Log event can be written to, and a read pointer
224 * indicates the location of the next Log event to be sent to the
225 * user's transport function. Log write calls cause the write pointer
226 * to advance, and when Log data is passed to the user's transport
227 * function in the idle loop, the read pointer advances. If the
228 * read pointer catches up the the write pointer, the buffer is
229 * 'empty', and if the write pointer catches up the the read pointer,
230 * the buffer is full.
231 *
232 * The LoggerIdle buffer will fill up, if the idle function to output
233 * the Log data cannot keep up with the Log writes. When this happens,
234 * if writeWhenFull is false, Log writes will not put any new data
235 * into the buffer until the LoggerIdle transportFxn has been called
236 * to empty some of the buffer. As a result, the most recent Log
237 * events could be lost. This is a simple solution to dealing with a
238 * full buffer. Since Log event sizes vary, it avoids having to
239 * determine how much the read pointer must be adjusted to fit a new
240 * Log event. It also allows you to send a large chunk of the buffer
241 * to the transport function in one shot, since the data will not
242 * be overwritten by Log writes during the transfer. If Log events
243 * are infrequent or the idle time is sufficient to get the Log
244 * data out, then disabling writeWhenFull may be appropriate.
245 *
246 * When this flag is set to true, if the LoggerIdle buffer is full,
247 * new Log data will be written over the oldest Log record(s) in the
248 * buffer. The oldest Log records in the buffer will be lost when
249 * this happens.
250 *
251 * The cost of enabling writeWhenFull is an increase in Log write
252 * times when the buffer is full, as the buffer's read pointer will
253 * need adjusting. There is also more overhead to get the Log data
254 * out through the transport function. When writeWhenFull is enabled,
255 * LoggerIdle's idle function will copy one Log record at a time into
256 * a temporary buffer, and send the temporary buffer to the user's
257 * transport function. This is to minimize interrupt latency, as the
258 * buffer's read pointer can now be modified by both the idle function
259 * and Log writes, and must be protected. The advantage, though, is
260 * that you will not lose the most recent Log data when the buffer is
261 * full. If Log events are frequent and the idle time is insufficient
262 * to get the Log data out, then enabling writeWhenFull may be
263 * appropriate.
264 */
265 config Bool writeWhenFull = false;
266
267 /*!
268 * @_nodoc
269 * ======== L_test ========
270 * Event used for benchmark tests
271 */
272 config xdc.runtime.Log.Event L_test = {
273 mask: xdc.runtime.Diags.USER1,
274 msg: "Test Event"
275 };
276
277 /*!
278 * ======== flush ========
279 * Call the transport function to empty out the LoggerIdle buffer.
280 *
281 * This API is not intended for general use, but could be used for
282 * example, in an exception handler to recover the most recent Log
283 * data that was written after the last run of the idle loop.
284 *
285 * NOTE: Calling LoggerIdle_flush() when the idle task was in the
286 * middle of outputting data can result in lost data. Since the idle
287 * function only outputs one Log record at a time, so at most one record
288 * could be lost.
289 */
290 Void flush();
291
292 /*!
293 * @_nodoc
294 * ======== initDecoder ========
295 * Initialize the Java LoggerIdleDecoder for use in the LoggerIdle
296 * 'Records' ROV view.
297 */
298 function initDecoder();
299
300 instance:
301 /*!
302 * ======== create ========
303 * Create a `LoggerIdle` logger
304 *
305 * The logger instance will route all log events it receives to
306 * the Uart.
307 */
308 create();
309
310 @DirectCall
311 override Void write0(xdc.runtime.Log.Event evt, xdc.runtime.Types.ModuleId mid);
312
313 @DirectCall
314 override Void write1(xdc.runtime.Log.Event evt, xdc.runtime.Types.ModuleId mid,
315 IArg a1);
316
317 @DirectCall
318 override Void write2(xdc.runtime.Log.Event evt, xdc.runtime.Types.ModuleId mid,
319 IArg a1, IArg a2);
320
321 @DirectCall
322 override Void write4(xdc.runtime.Log.Event evt, xdc.runtime.Types.ModuleId mid,
323 IArg a1, IArg a2, IArg a3, IArg a4);
324
325 @DirectCall
326 override Void write8(xdc.runtime.Log.Event evt, xdc.runtime.Types.ModuleId mid,
327 IArg a1, IArg a2, IArg a3, IArg a4,
328 IArg a5, IArg a6, IArg a7, IArg a8);
329
330 internal:
331
332 /*!
333 * ======== idleWrite =========
334 * Idle function that calls the transport function.
335 */
336 Void idleWrite();
337
338 /*!
339 * ======== idleWriteEvent =========
340 * Idle function that calls the transport function to write one
341 * Log event.
342 */
343 Void idleWriteEvent();
344
345 Void write(Log.Event evt, xdc.runtime.Types.ModuleId mid,
346 IArg numEventWords,
347 IArg a1, IArg a2, IArg a3, IArg a4,
348 IArg a5, IArg a6, IArg a7, IArg a8);
349
350 struct Module_State {
351 LoggerFxn loggerFxn;
352 Bool enabled;
353 Bool empty;
354 UInt bufferSize;
355 UInt32 idleBuffer[];
356 UInt32 tempBuffer[];
357 UInt32 *bufferRead;
358 UInt32 *bufferWrite;
359 UInt32 *bufferPad; 360
361 UInt32 *bufferEnd;
362 UInt16 eventSequenceNum;
363 };
364
365 struct Instance_State {
366 };
367 }