edc55c5992755779ca859d9c9081df49cd00748a
[fw/openocd] / 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  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
21  ***************************************************************************/
22
23 #include "dcc_stdio.h"
24
25 #if defined(__ARM_ARCH_7M__)
26
27 /* we use the cortex_m3 DCRDR reg to simulate a arm7_9 dcc channel
28  * DCRDR[7:0] is used by target for status
29  * DCRDR[15:8] is used by target for write buffer
30  * DCRDR[23:16] is used for by host for status
31  * DCRDR[31:24] is used for by host for write buffer */
32
33 #define DCRDR_WRSTS     *((volatile u8*)0xE000EDF8)
34 #define DCRDR_WRDAT     *((volatile u8*)0xE000EDF9)
35
36 #define BUSY    1
37
38 void dbg_write(u32 dcc_data)
39 {
40         int len = 4;
41         
42         while (len--)
43         {
44                 /* wait for data ready */
45                 while (DCRDR_WRSTS & BUSY);
46                 
47                 /* write our data */
48                 DCRDR_WRDAT = (u8)(dcc_data & 0xff);
49                 /* set write flag - tell host there is data */
50                 DCRDR_WRSTS = BUSY;
51                 dcc_data >>= 8;
52         }
53 }
54
55 #elif defined(__ARM_ARCH_4T__) || defined(__ARM_ARCH_5TE__)
56                                         
57 void dbg_write(u32 dcc_data)
58 {
59         u32 dcc_status;
60         
61         do {
62                 asm volatile("mrc p14, 0, %0, c0, c0" : "=r" (dcc_status));
63         } while (dcc_status & 0x2);
64         
65         asm volatile("mcr p14, 0, %0, c1, c0" : : "r" (dcc_data));
66 }
67
68 #else
69  #error unsupported target
70 #endif
71
72
73 void dbg_write_u32(u32 *val, u32 len)
74 {       
75         dbg_write(0x01 | 0x0400 | ((len & 0xffff) << 16));
76
77         while (len > 0)
78         {
79                 dbg_write(*val);
80                 
81                 val++;
82                 len--;
83         }
84 }
85
86 void dbg_write_u16(u16 *val, u32 len)
87 {
88         u32 dcc_data;
89                 
90         dbg_write(0x01 | 0x0200 | ((len & 0xffff) << 16));
91
92         while (len > 0)
93         {
94                 dcc_data = val[0] | (val[1] << 8)
95                         | ((len > 1) ? (val[2] | (val[3] << 8)) << 16 : 0x00);
96                 
97                 dbg_write(dcc_data);
98                 
99                 val += 2;
100                 len -= 2;
101         }
102 }
103
104 void dbg_write_u8(u8 *val, u32 len)
105 {       
106         u32 dcc_data;
107
108         dbg_write(0x01 | 0x0100 | ((len & 0xffff) << 16));
109
110         while (len > 0)
111         {
112                 dcc_data = val[0]
113                         | ((len > 1) ? val[1] << 8 : 0x00)
114                         | ((len > 2) ? val[2] << 16 : 0x00)
115                         | ((len > 3) ? val[3] << 24 : 0x00);
116                 
117                 dbg_write(dcc_data);
118                 
119                 val += 2;
120                 len -= 2;
121         }
122 }
123
124 void dbg_write_str(u8 *msg)
125 {
126         int len;
127         u32 dcc_data;
128         
129         for (len = 0; msg[len] && (len < 65536); len++);
130         
131         dbg_write(0x01 | ((len & 0xffff) << 16));
132         
133         while (len > 0)
134         {               
135                 dcc_data = msg[0]
136                         | ((len > 1) ? msg[1] << 8 : 0x00)
137                         | ((len > 2) ? msg[2] << 16 : 0x00)
138                         | ((len > 3) ? msg[3] << 24 : 0x00);
139                 dbg_write(dcc_data);
140                 
141                 msg += 4;
142                 len -= 4;
143         }
144 }
145
146 void dbg_write_char(u8 msg)
147 {       
148         dbg_write(0x02 | ((msg & 0xff) << 16));
149 }