1 /*  alt_log_printf.h
2  *
3  *  ALT_LOG is designed to provide extra logging/debugging messages from HAL
4  *  through a different port than stdout.  It is enabled by the ALT_LOG_ENABLE
5  *  define, which needs to supplied at compile time.  When logging is turned off,
6  *  code size is unaffected.  Thus, this should be transparent to the user
7  *  when it is not actively turned on, and should not affect projects in any way.
8  *
9  *  There are macros sprinkled within different components, such as the jtag uart
10  *  and timer, in the HAL code.  They are always named ALT_LOG_<name>, and can be
11  *  safely ignored if ALT_LOG is turned off.
12  *
13  *  To turn on ALT_LOG, ALT_LOG_ENABLE must be defined, and ALT_LOG_PORT_TYPE and
14  *  ALT_LOG_PORT_BASE must be set in system.h.  This is done through editing
15  *  <project>.ptf, by editing the alt_log_port_type & alt_log_port_base settings.
16  *  See the documentation html file for examples.
17  *
18  *  When it is turned on, it will output extra HAL messages to a port specified
19  *  in system.h.  This can be a UART or JTAG UART port.  By default it will
20  *  output boot messages, detailing every step of the boot process.
21  *
22  *  Extra logging is designed to be enabled by flags, which are defined in
23  *  alt_log_printf.c.  The default value is that all flags are off, so only the
24  *  boot up logging messages show up.  ALT_LOG_FLAGS can be set to enable certain
25  *  groupings of flags, and that grouping is done in this file.  Each flag can
26  *  also be overridden with a -D at compile time.
27  *
28  *  This header file includes the necessary prototypes for using the alt_log
29  *  functions.  It also contains all the macros that are used to remove the code
30  *  from alt log is turned off.  Also, the macros in other HAL files are defined
31  *  here at the bottom.  These macros all call some C function that is in
32  *  alt_log_printf.c.
33  *
34  *  The logging has functions for printing in C (ALT_LOG_PRINTF) and in assembly
35  *  (ALT_LOG_PUTS).  This was needed because the assembly printing occurs before
36  *  the device is initialized.  The assembly function corrupts register R4-R7,
37  *  which are not used in the normal boot process.  For this reason, do not call
38  *  the assembly function in C.
39  *
40  *  author: gkwan
41  */
42 
43 
44 #ifndef __ALT_LOG_PRINTF_H__
45 #define __ALT_LOG_PRINTF_H__
46 
47 #include <system.h>
48 
49 /* Global switch to turn on logging functions */
50 #ifdef ALT_LOG_ENABLE
51 
52     /* ALT_LOG_PORT_TYPE values as defined in system.h.  They are defined as
53      * numbers here first becasue the C preprocessor does not handle string
54      * comparisons.  */
55     #define ALTERA_AVALON_JTAG_UART 1
56     #define ALTERA_AVALON_UART 0
57 
58     /* If this .h file is included by an assembly file, skip over include files
59      * that won't compile in assembly. */
60     #ifndef ALT_ASM_SRC
61         #include <stdarg.h>
62         #include "sys/alt_alarm.h"
63         #include "sys/alt_dev.h"
64         #ifdef __ALTERA_AVALON_JTAG_UART
65             #include "altera_avalon_jtag_uart.h"
66         #endif
67     #endif /* ALT_ASM_SRC */
68 
69     /* These are included for the port register offsets and masks, needed
70      * to write to the port.  Only include if the port type is set correctly,
71      * otherwise error.  If alt_log is turned on and the port to output to is
72      * incorrect or does not exist, then should exit. */
73     #if ALT_LOG_PORT_TYPE == ALTERA_AVALON_JTAG_UART
74         #ifdef __ALTERA_AVALON_JTAG_UART
75             #include <altera_avalon_jtag_uart_regs.h>
76         #else
77             #error ALT_LOG: JTAG_UART port chosen, but no JTAG_UART in system.
78         #endif
79     #elif ALT_LOG_PORT_TYPE == ALTERA_AVALON_UART
80         #ifdef __ALTERA_AVALON_UART
81             #include <altera_avalon_uart_regs.h>
82         #else
83             #error ALT_LOG: UART Port chosen, but no UART in system.
84         #endif
85     #else
86         #error ALT_LOG: alt_log_port_type declaration invalid!
87     #endif
88 
89     /* ALT_LOG_ENABLE turns on the basic printing function */
90     #define ALT_LOG_PRINTF(...) do {alt_log_printf_proc(__VA_ARGS__);} while (0)
91 
92     /* Assembly macro for printing in assembly, calls tx_log_str
93      * which is in alt_log_macro.S.
94      * If alt_log_boot_on_flag is 0, skips the printing */
95     #define ALT_LOG_PUTS(str) movhi r4, %hiadj(alt_log_boot_on_flag) ; \
96          addi r4, r4, %lo(alt_log_boot_on_flag) ; \
97          ldwio r5, 0(r4) ; \
98          beq r0, r5, 0f ; \
99          movhi r4, %hiadj(str) ; \
100          addi r4, r4, %lo(str) ; \
101 	 call tx_log_str ; \
102        0:
103 
104     /* These defines are here to faciliate the use of one output function
105      * (alt_log_txchar) to print to both the JTAG UART or the UART. Depending
106      * on the port type, the status register, read mask, and output register
107      * are set to the appropriate value for the port.  */
108     #if ALT_LOG_PORT_TYPE == ALTERA_AVALON_JTAG_UART
109       #define ALT_LOG_PRINT_REG_RD IORD_ALTERA_AVALON_JTAG_UART_CONTROL
110       #define ALT_LOG_PRINT_MSK ALTERA_AVALON_JTAG_UART_CONTROL_WSPACE_MSK
111       #define ALT_LOG_PRINT_TXDATA_WR IOWR_ALTERA_AVALON_JTAG_UART_DATA
112       #define ALT_LOG_PRINT_REG_OFFSET (ALTERA_AVALON_JTAG_UART_CONTROL_REG*0x4)
113       #define ALT_LOG_PRINT_TXDATA_REG_OFFSET (ALTERA_AVALON_JTAG_UART_DATA_REG*0x4)
114     #elif ALT_LOG_PORT_TYPE == ALTERA_AVALON_UART
115       #define ALT_LOG_PRINT_REG_RD IORD_ALTERA_AVALON_UART_STATUS
116       #define ALT_LOG_PRINT_MSK ALTERA_AVALON_UART_STATUS_TRDY_MSK
117       #define ALT_LOG_PRINT_TXDATA_WR IOWR_ALTERA_AVALON_UART_TXDATA
118       #define ALT_LOG_PRINT_REG_OFFSET (ALTERA_AVALON_UART_STATUS_REG*0x4)
119       #define ALT_LOG_PRINT_TXDATA_REG_OFFSET (ALTERA_AVALON_UART_TXDATA_REG*0x4)
120     #endif /* ALT_LOG_PORT */
121 
122     /* Grouping of flags via ALT_LOG_FLAGS.  Each specific flag can be set via
123      * -D at compile time, or else they'll be set to a default value according
124      * to ALT_LOG_FLAGS.  ALT_LOG_FLAGS = 0 or not set is the default, where
125      * only the boot messages will be printed. As ALT_LOG_FLAGS increase, they
126      * increase in intrusiveness to the program, and will affect performance.
127      *
128      * Flag Level 1 - turns on system clock and JTAG UART startup status
129      *            2 - turns on write echo and JTAG_UART alarm (periodic report)
130      *            3 - turns on JTAG UART ISR logging - will slow performance
131      *                significantly.
132      *           -1 - All logging output is off, but if ALT_LOG_ENABLE is
133      *                defined all logging function is built and code size
134      *                remains constant
135      *
136      * Flag settings - 1 = on, 0 = off. */
137 
138     /* This flag turns on "boot" messages for printing.  This includes messages
139      * during crt0.S, then alt_main, and finally alt_exit. */
140     #ifndef ALT_LOG_BOOT_ON_FLAG_SETTING
141         #if ALT_LOG_FLAGS == 1
142             #define ALT_LOG_BOOT_ON_FLAG_SETTING 0x1
143         #elif ALT_LOG_FLAGS == 2
144             #define ALT_LOG_BOOT_ON_FLAG_SETTING 0x1
145         #elif ALT_LOG_FLAGS == 3
146             #define ALT_LOG_BOOT_ON_FLAG_SETTING 0x1
147         #elif ALT_LOG_FLAGS == -1 /* silent mode */
148             #define ALT_LOG_BOOT_ON_FLAG_SETTING 0x0
149         #else /* default setting */
150             #define ALT_LOG_BOOT_ON_FLAG_SETTING 0x1
151         #endif
152     #endif /* ALT_LOG_BOOT_ON_FLAG_SETTING */
153 
154     #ifndef ALT_LOG_SYS_CLK_ON_FLAG_SETTING
155         #if ALT_LOG_FLAGS == 1
156             #define ALT_LOG_SYS_CLK_ON_FLAG_SETTING 0x1
157         #elif ALT_LOG_FLAGS == 2
158             #define ALT_LOG_SYS_CLK_ON_FLAG_SETTING 0x1
159         #elif ALT_LOG_FLAGS == 3
160             #define ALT_LOG_SYS_CLK_ON_FLAG_SETTING 0x1
161         #elif ALT_LOG_FLAGS == -1 /* silent mode */
162             #define ALT_LOG_SYS_CLK_ON_FLAG_SETTING 0x0
163         #else /* default setting */
164             #define ALT_LOG_SYS_CLK_ON_FLAG_SETTING 0x0
165         #endif
166     #endif /* ALT_LOG_SYS_CLK_ON_FLAG_SETTING */
167 
168     #ifndef ALT_LOG_WRITE_ON_FLAG_SETTING
169         #if ALT_LOG_FLAGS == 1
170             #define ALT_LOG_WRITE_ON_FLAG_SETTING 0x0
171         #elif ALT_LOG_FLAGS == 2
172             #define ALT_LOG_WRITE_ON_FLAG_SETTING 0x1
173         #elif ALT_LOG_FLAGS == 3
174             #define ALT_LOG_WRITE_ON_FLAG_SETTING 0x1
175         #elif ALT_LOG_FLAGS == -1 /* silent mode */
176             #define ALT_LOG_WRITE_ON_FLAG_SETTING 0x0
177         #else /* default setting */
178             #define ALT_LOG_WRITE_ON_FLAG_SETTING 0x0
179         #endif
180     #endif /* ALT_LOG_WRITE_ON_FLAG_SETTING */
181 
182     #ifndef ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING
183         #ifndef __ALTERA_AVALON_JTAG_UART
184             #define ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING 0x0
185         #elif ALT_LOG_FLAGS == 1
186             #define ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING 0x0
187         #elif ALT_LOG_FLAGS == 2
188             #define ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING 0x1
189         #elif ALT_LOG_FLAGS == 3
190             #define ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING 0x1
191         #elif ALT_LOG_FLAGS == -1 /* silent mode */
192             #define ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING 0x0
193         #else /* default setting */
194             #define ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING 0x0
195         #endif
196     #endif /* ALT_LOG_JTAG_UART_ALARM_ON_FLAG_SETTING */
197 
198     #ifndef ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING
199         #ifndef __ALTERA_AVALON_JTAG_UART
200             #define ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING 0x0
201         #elif ALT_LOG_FLAGS == 1
202             #define ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING 0x1
203         #elif ALT_LOG_FLAGS == 2
204             #define ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING 0x1
205         #elif ALT_LOG_FLAGS == 3
206             #define ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING 0x1
207         #elif ALT_LOG_FLAGS == -1 /* silent mode */
208             #define ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING 0x0
209         #else /* default setting */
210             #define ALT_LOG_JTAG_UART_STARTUP_INFO_ON_FLAG_SETTING 0x0
211         #endif
212     #endif /* ALT_LOG_JTAG_UART_STARTUP_INFO_FLAG_SETTING */
213 
214     #ifndef ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING
215         #ifndef __ALTERA_AVALON_JTAG_UART
216             #define ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING 0x0
217         #elif ALT_LOG_FLAGS == 1
218             #define ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING 0x0
219         #elif ALT_LOG_FLAGS == 2
220             #define ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING 0x0
221         #elif ALT_LOG_FLAGS == 3
222             #define ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING 0x1
223         #elif ALT_LOG_FLAGS == -1 /* silent mode */
224             #define ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING 0x0
225         #else /* default setting */
226             #define ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING 0x0
227         #endif
228     #endif /* ALT_LOG_JTAG_UART_ISR_ON_FLAG_SETTING */
229 
230 #ifndef ALT_ASM_SRC
231     /* Function Prototypes */
232     void alt_log_txchar(int c,char *uartBase);
233     void alt_log_private_printf(const char *fmt,int base,va_list args);
234     void alt_log_repchar(char c,int r,int base);
235     int alt_log_printf_proc(const char *fmt, ... );
236     void alt_log_system_clock();
237     #ifdef __ALTERA_AVALON_JTAG_UART
238         alt_u32 altera_avalon_jtag_uart_report_log(void * context);
239         void alt_log_jtag_uart_startup_info(altera_avalon_jtag_uart_state* dev, int base);
240         void alt_log_jtag_uart_print_control_reg(altera_avalon_jtag_uart_state* dev, \
241              int base, const char* header);
242         void alt_log_jtag_uart_isr_proc(int base, altera_avalon_jtag_uart_state* dev);
243     #endif
244     void alt_log_write(const void *ptr, size_t len);
245 
246     /* extern all global variables */
247     /* CASE:368514 - The boot message flag is linked into the sdata section
248      * because if it is zero, it would otherwise be placed in the bss section.
249      * alt_log examines this variable before the BSS is cleared in the boot-up
250      * process.
251      */
252     extern volatile alt_u32 alt_log_boot_on_flag __attribute__ ((section (".sdata")));
253     extern volatile alt_u8 alt_log_write_on_flag;
254     extern volatile alt_u8 alt_log_sys_clk_on_flag;
255     extern volatile alt_u8 alt_log_jtag_uart_alarm_on_flag;
256     extern volatile alt_u8 alt_log_jtag_uart_isr_on_flag;
257     extern volatile alt_u8 alt_log_jtag_uart_startup_info_on_flag;
258     extern volatile int alt_log_sys_clk_count;
259     extern volatile int alt_system_clock_in_sec;
260     extern alt_alarm alt_log_jtag_uart_alarm_1;
261 #endif  /* ALT_ASM_SRC */
262 
263 
264     /* Below are the MACRO defines used in various HAL files.  They check
265      * if their specific flag is turned on; if it is, then it executes its
266      * code.
267      *
268      * To keep this file reasonable, most of these macros calls functions,
269      * which are defined in alt_log_printf.c.  Look there for implementation
270      * details. */
271 
272     /* Boot Messages Logging */
273     #define ALT_LOG_PRINT_BOOT(...) \
274        do { if (alt_log_boot_on_flag==1) {ALT_LOG_PRINTF(__VA_ARGS__);} \
275           } while (0)
276 
277     /* JTAG UART Logging */
278     /* number of ticks before alarm runs logging function */
279     #ifndef ALT_LOG_JTAG_UART_TICKS_DIVISOR
280     	#define ALT_LOG_JTAG_UART_TICKS_DIVISOR 10
281     #endif
282     #ifndef ALT_LOG_JTAG_UART_TICKS
283         #define ALT_LOG_JTAG_UART_TICKS \
284         	(alt_ticks_per_second()/ALT_LOG_JTAG_UART_TICKS_DIVISOR)
285     #endif
286 
287     /* if there's a JTAG UART defined, then enable these macros */
288     #ifdef __ALTERA_AVALON_JTAG_UART
289 
290         /* Macro in altera_avalon_jtag_uart.c, to register the alarm function.
291          * Also, the startup register info is also printed here, as this is
292          * called within the device driver initialization.  */
293         #define ALT_LOG_JTAG_UART_ALARM_REGISTER(dev, base) \
294             do { if (alt_log_jtag_uart_alarm_on_flag==1) { \
295                     alt_alarm_start(&alt_log_jtag_uart_alarm_1, \
296                     ALT_LOG_JTAG_UART_TICKS, &altera_avalon_jtag_uart_report_log,\
297                     dev);} \
298                  if (alt_log_jtag_uart_startup_info_on_flag==1) {\
299                     alt_log_jtag_uart_startup_info(dev, base);} \
300                } while (0)
301 
302         /* JTAG UART IRQ Logging (when buffer is empty)
303          * Inserted in the ISR in altera_avalon_jtag_uart.c */
304         #define ALT_LOG_JTAG_UART_ISR_FUNCTION(base, dev) \
305             do { alt_log_jtag_uart_isr_proc(base, dev); } while (0)
306     /* else, define macros to nothing.  Or else the jtag_uart specific types
307      * will throw compiler errors */
308     #else
309         #define ALT_LOG_JTAG_UART_ALARM_REGISTER(dev, base)
310         #define ALT_LOG_JTAG_UART_ISR_FUNCTION(base, dev)
311     #endif
312 
313     /* System clock logging
314      * How often (in seconds) the system clock logging prints.
315      * The default value is every 1 second */
316     #ifndef ALT_LOG_SYS_CLK_INTERVAL_MULTIPLIER
317 	#define ALT_LOG_SYS_CLK_INTERVAL_MULTIPLIER 1
318     #endif
319     #ifndef ALT_LOG_SYS_CLK_INTERVAL
320 	#define ALT_LOG_SYS_CLK_INTERVAL \
321 	    (alt_ticks_per_second()*ALT_LOG_SYS_CLK_INTERVAL_MULTIPLIER)
322     #endif
323 
324     /* System clock logging - prints a message every interval (set above)
325      * to show that the system clock is alive.
326      * This macro is used in altera_avalon_timer_sc.c */
327     #define ALT_LOG_SYS_CLK_HEARTBEAT() \
328     	do { alt_log_system_clock(); } while (0)
329 
330     /* alt_write_logging - echos a message every time write() is called,
331      * displays the first ALT_LOG_WRITE_ECHO_LEN characters.
332      * This macro is used in alt_write.c */
333     #ifndef ALT_LOG_WRITE_ECHO_LEN
334         #define ALT_LOG_WRITE_ECHO_LEN 15
335     #endif
336 
337     #define ALT_LOG_WRITE_FUNCTION(ptr,len) \
338         do { alt_log_write(ptr,len); } while (0)
339 
340 #else /* ALT_LOG_ENABLE not defined */
341 
342     /* logging is off, set all relevant macros to null */
343     #define ALT_LOG_PRINT_BOOT(...)
344     #define ALT_LOG_PRINTF(...)
345     #define ALT_LOG_JTAG_UART_ISR_FUNCTION(base, dev)
346     #define ALT_LOG_JTAG_UART_ALARM_REGISTER(dev, base)
347     #define ALT_LOG_SYS_CLK_HEARTBEAT()
348     #define ALT_LOG_PUTS(str)
349     #define ALT_LOG_WRITE_FUNCTION(ptr,len)
350 
351 #endif /* ALT_LOG_ENABLE */
352 
353 #endif /* __ALT_LOG_PRINTF_H__ */
354