Remove FSF mailing address.
[openocd.git] / contrib / libdcc / dcc_stdio.c
1 /***************************************************************************
2 * Copyright (C) 2008 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * Copyright (C) 2008 by Spencer Oliver *
5 * spen@spen-soft.co.uk *
6 * Copyright (C) 2008 by Frederik Kriewtz *
7 * frederik@kriewitz.eu *
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 * This program is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU General Public License *
20 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
21 ***************************************************************************/
22
23 #include "dcc_stdio.h"
24
25 #define TARGET_REQ_TRACEMSG 0x00
26 #define TARGET_REQ_DEBUGMSG_ASCII 0x01
27 #define TARGET_REQ_DEBUGMSG_HEXMSG(size) (0x01 | ((size & 0xff) << 8))
28 #define TARGET_REQ_DEBUGCHAR 0x02
29
30 #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_6SM__)
31
32 /* we use the System Control Block DCRDR reg to simulate a arm7_9 dcc channel
33 * DCRDR[7:0] is used by target for status
34 * DCRDR[15:8] is used by target for write buffer
35 * DCRDR[23:16] is used for by host for status
36 * DCRDR[31:24] is used for by host for write buffer */
37
38 #define NVIC_DBG_DATA_R (*((volatile unsigned short *)0xE000EDF8))
39
40 #define BUSY 1
41
42 void dbg_write(unsigned long dcc_data)
43 {
44 int len = 4;
45
46 while (len--)
47 {
48 /* wait for data ready */
49 while (NVIC_DBG_DATA_R & BUSY);
50
51 /* write our data and set write flag - tell host there is data*/
52 NVIC_DBG_DATA_R = (unsigned short)(((dcc_data & 0xff) << 8) | BUSY);
53 dcc_data >>= 8;
54 }
55 }
56
57 #elif defined(__ARM_ARCH_4T__) || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5T__)
58
59 void dbg_write(unsigned long dcc_data)
60 {
61 unsigned long dcc_status;
62
63 do {
64 asm volatile("mrc p14, 0, %0, c0, c0" : "=r" (dcc_status));
65 } while (dcc_status & 0x2);
66
67 asm volatile("mcr p14, 0, %0, c1, c0" : : "r" (dcc_data));
68 }
69
70 #else
71 #error unsupported target
72 #endif
73
74 void dbg_trace_point(unsigned long number)
75 {
76 dbg_write(TARGET_REQ_TRACEMSG | (number << 8));
77 }
78
79 void dbg_write_u32(const unsigned long *val, long len)
80 {
81 dbg_write(TARGET_REQ_DEBUGMSG_HEXMSG(4) | ((len & 0xffff) << 16));
82
83 while (len > 0)
84 {
85 dbg_write(*val);
86
87 val++;
88 len--;
89 }
90 }
91
92 void dbg_write_u16(const unsigned short *val, long len)
93 {
94 unsigned long dcc_data;
95
96 dbg_write(TARGET_REQ_DEBUGMSG_HEXMSG(2) | ((len & 0xffff) << 16));
97
98 while (len > 0)
99 {
100 dcc_data = val[0]
101 | ((len > 1) ? val[1] << 16: 0x0000);
102
103 dbg_write(dcc_data);
104
105 val += 2;
106 len -= 2;
107 }
108 }
109
110 void dbg_write_u8(const unsigned char *val, long len)
111 {
112 unsigned long dcc_data;
113
114 dbg_write(TARGET_REQ_DEBUGMSG_HEXMSG(1) | ((len & 0xffff) << 16));
115
116 while (len > 0)
117 {
118 dcc_data = val[0]
119 | ((len > 1) ? val[1] << 8 : 0x00)
120 | ((len > 2) ? val[2] << 16 : 0x00)
121 | ((len > 3) ? val[3] << 24 : 0x00);
122
123 dbg_write(dcc_data);
124
125 val += 4;
126 len -= 4;
127 }
128 }
129
130 void dbg_write_str(const char *msg)
131 {
132 long len;
133 unsigned long dcc_data;
134
135 for (len = 0; msg[len] && (len < 65536); len++);
136
137 dbg_write(TARGET_REQ_DEBUGMSG_ASCII | ((len & 0xffff) << 16));
138
139 while (len > 0)
140 {
141 dcc_data = msg[0]
142 | ((len > 1) ? msg[1] << 8 : 0x00)
143 | ((len > 2) ? msg[2] << 16 : 0x00)
144 | ((len > 3) ? msg[3] << 24 : 0x00);
145 dbg_write(dcc_data);
146
147 msg += 4;
148 len -= 4;
149 }
150 }
151
152 void dbg_write_char(char msg)
153 {
154 dbg_write(TARGET_REQ_DEBUGCHAR | ((msg & 0xff) << 16));
155 }