1 /*
2  * @brief	IO redirection support
3  *
4  * This file adds re-direction support to the library for various
5  * projects. It can be configured in one of 3 ways - no redirection,
6  * redirection via a UART, or redirection via semihosting. If DEBUG
7  * is not defined, all printf statements will do nothing with the
8  * output being throw away. If DEBUG is defined, then the choice of
9  * output is selected by the DEBUG_SEMIHOSTING define. If the
10  * DEBUG_SEMIHOSTING is not defined, then output is redirected via
11  * the UART. If DEBUG_SEMIHOSTING is defined, then output will be
12  * attempted to be redirected via semihosting. If the UART method
13  * is used, then the Board_UARTPutChar and Board_UARTGetChar
14  * functions must be defined to be used by this driver and the UART
15  * must already be initialized to the correct settings.
16  *
17  * @note
18  * Copyright(C) NXP Semiconductors, 2012
19  * All rights reserved.
20  *
21  * @par
22  * Software that is described herein is for illustrative purposes only
23  * which provides customers with programming information regarding the
24  * LPC products.  This software is supplied "AS IS" without any warranties of
25  * any kind, and NXP Semiconductors and its licensor disclaim any and
26  * all warranties, express or implied, including all implied warranties of
27  * merchantability, fitness for a particular purpose and non-infringement of
28  * intellectual property rights.  NXP Semiconductors assumes no responsibility
29  * or liability for the use of the software, conveys no license or rights under any
30  * patent, copyright, mask work right, or any other intellectual property rights in
31  * or to any products. NXP Semiconductors reserves the right to make changes
32  * in the software without notification. NXP Semiconductors also makes no
33  * representation or warranty that such application will be suitable for the
34  * specified use without further testing or modification.
35  *
36  * @par
37  * Permission to use, copy, modify, and distribute this software and its
38  * documentation is hereby granted, under NXP Semiconductors' and its
39  * licensor's relevant copyrights in the software, without fee, provided that it
40  * is used in conjunction with NXP Semiconductors microcontrollers.  This
41  * copyright, permission, and disclaimer notice must appear in all copies of
42  * this code.
43  */
44 
45 #include "board.h"
46 
47 /* Keil (Realview) support */
48 #if defined(__CC_ARM)
49 
50 #include <stdio.h>
51 #include <rt_misc.h>
52 
53 #if defined(DEBUG_ENABLE)
54 #if defined(DEBUG_SEMIHOSTING)
55 #define ITM_Port8(n)    (*((volatile unsigned char *) (0xE0000000 + 4 * n)))
56 #define ITM_Port16(n)   (*((volatile unsigned short *) (0xE0000000 + 4 * n)))
57 #define ITM_Port32(n)   (*((volatile unsigned long *) (0xE0000000 + 4 * n)))
58 
59 #define DEMCR           (*((volatile unsigned long *) (0xE000EDFC)))
60 #define TRCENA          0x01000000
61 
62 /* Write to SWO */
_ttywrch(int ch)63 void _ttywrch(int ch)
64 {
65 	if (DEMCR & TRCENA) {
66 		while (ITM_Port32(0) == 0) {}
67 		ITM_Port8(0) = ch;
68 	}
69 }
70 
71 #else
BoardOutChar(char ch)72 static INLINE void BoardOutChar(char ch)
73 {
74 	Board_UARTPutChar(ch);
75 }
76 
77 #endif /* defined(DEBUG_SEMIHOSTING) */
78 #endif /* defined(DEBUG_ENABLE) */
79 
80 struct __FILE {
81 	int handle;
82 };
83 
84 FILE __stdout;
85 FILE __stdin;
86 FILE __stderr;
87 
_sys_open(const char * name,int openmode)88 void *_sys_open(const char *name, int openmode)
89 {
90 	return 0;
91 }
92 
fputc(int c,FILE * f)93 int fputc(int c, FILE *f)
94 {
95 #if defined(DEBUG_ENABLE)
96 #if defined(DEBUG_SEMIHOSTING)
97 	_ttywrch(c);
98 #else
99 	BoardOutChar((char) c);
100 #endif
101 #endif
102 	return 0;
103 }
104 
fgetc(FILE * f)105 int fgetc(FILE *f)
106 {
107 #if defined(DEBUG_ENABLE) && !defined(DEBUG_SEMIHOSTING)
108 	return Board_UARTGetChar();
109 #else
110 	return 0;
111 #endif
112 }
113 
ferror(FILE * f)114 int ferror(FILE *f)
115 {
116 	return EOF;
117 }
118 
_sys_exit(int return_code)119 void _sys_exit(int return_code)
120 {
121 label:
122 	__WFI();
123 	goto label;	/* endless loop */
124 }
125 
126 #endif /* defined (__CC_ARM) */
127 
128 /* IAR support */
129 #if defined(__ICCARM__)
130 /*******************
131  *
132  * Copyright 1998-2003 IAR Systems.  All rights reserved.
133  *
134  * $Revision: 30870 $
135  *
136  * This is a template implementation of the "__write" function used by
137  * the standard library.  Replace it with a system-specific
138  * implementation.
139  *
140  * The "__write" function should output "size" number of bytes from
141  * "buffer" in some application-specific way.  It should return the
142  * number of characters written, or _LLIO_ERROR on failure.
143  *
144  * If "buffer" is zero then __write should perform flushing of
145  * internal buffers, if any.  In this case "handle" can be -1 to
146  * indicate that all handles should be flushed.
147  *
148  * The template implementation below assumes that the application
149  * provides the function "MyLowLevelPutchar".  It should return the
150  * character written, or -1 on failure.
151  *
152  ********************/
153 
154 #include <yfuns.h>
155 
156 #if defined(DEBUG_ENABLE) && !defined(DEBUG_SEMIHOSTING)
157 
158 _STD_BEGIN
159 
160 #pragma module_name = "?__write"
161 
162 /*
163    If the __write implementation uses internal buffering, uncomment
164    the following line to ensure that we are called with "buffer" as 0
165    (i.e. flush) when the application terminates. */
__write(int handle,const unsigned char * buffer,size_t size)166 size_t __write(int handle, const unsigned char *buffer, size_t size)
167 {
168 #if defined(DEBUG_ENABLE)
169 	size_t nChars = 0;
170 
171 	if (buffer == 0) {
172 		/*
173 		   This means that we should flush internal buffers.  Since we
174 		   don't we just return.  (Remember, "handle" == -1 means that all
175 		   handles should be flushed.)
176 		 */
177 		return 0;
178 	}
179 
180 	/* This template only writes to "standard out" and "standard err",
181 	   for all other file handles it returns failure. */
182 	if (( handle != _LLIO_STDOUT) && ( handle != _LLIO_STDERR) ) {
183 		return _LLIO_ERROR;
184 	}
185 
186 	for ( /* Empty */; size != 0; --size) {
187 		Board_UARTPutChar(*buffer++);
188 		++nChars;
189 	}
190 
191 	return nChars;
192 #else
193 	return size;
194 #endif /* defined(DEBUG_ENABLE) */
195 }
196 
197 _STD_END
198 #endif
199 
200 #endif /* defined (__ICCARM__) */
201 
202 #if defined( __GNUC__ )
203 /* Include stdio.h to pull in __REDLIB_INTERFACE_VERSION__ */
204 #include <stdio.h>
205 
206 #if (__REDLIB_INTERFACE_VERSION__ >= 20000)
207 /* We are using new Redlib_v2 semihosting interface */
208 	#define WRITEFUNC __sys_write
209 	#define READFUNC __sys_readc
210 #else
211 /* We are using original Redlib semihosting interface */
212 	#define WRITEFUNC __write
213 	#define READFUNC __readc
214 #endif
215 
216 #if defined(DEBUG_ENABLE)
217 #if defined(DEBUG_SEMIHOSTING)
218 /* Do nothing, semihosting is enabled by default in LPCXpresso */
219 #endif /* defined(DEBUG_SEMIHOSTING) */
220 #endif /* defined(DEBUG_ENABLE) */
221 
222 #if !defined(DEBUG_SEMIHOSTING)
WRITEFUNC(int iFileHandle,char * pcBuffer,int iLength)223 int WRITEFUNC(int iFileHandle, char *pcBuffer, int iLength)
224 {
225 #if defined(DEBUG_ENABLE)
226 	unsigned int i;
227 	for (i = 0; i < iLength; i++) {
228 		Board_UARTPutChar(pcBuffer[i]);
229 	}
230 #endif
231 
232 	return iLength;
233 }
234 
235 /* Called by bottom level of scanf routine within RedLib C library to read
236    a character. With the default semihosting stub, this would read the character
237    from the debugger console window (which acts as stdin). But this version reads
238    the character from the LPC1768/RDB1768 UART. */
READFUNC(void)239 int READFUNC(void)
240 {
241 #if defined(DEBUG_ENABLE)
242 	char c = Board_UARTGetChar();
243 	return (int) c;
244 
245 #else
246 	return (int) -1;
247 #endif
248 }
249 
250 #endif /* !defined(DEBUG_SEMIHOSTING) */
251 #endif /* defined ( __GNUC__ ) */
252