1 /* mdebug.c
2  *
3  * Copyright 2015 Brian Swetland <swetland@frotz.net>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <app.h>
19 #include <lk/debug.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <printf.h>
23 #include <dev/udc.h>
24 
25 #include <platform.h>
26 #include <arch/arm.h>
27 #include <kernel/thread.h>
28 #include <kernel/event.h>
29 
30 #include <platform/lpc43xx-gpio.h>
31 
32 #include "swd.h"
33 
34 #define TX_AHEAD 1
35 
36 static event_t txevt = EVENT_INITIAL_VALUE(txevt, TX_AHEAD, 0);
37 static event_t rxevt = EVENT_INITIAL_VALUE(rxevt, 0, 0);
38 
39 static udc_request_t *txreq;
40 static udc_request_t *rxreq;
41 static udc_endpoint_t *txept;
42 static udc_endpoint_t *rxept;
43 
44 static volatile int online;
45 static volatile int txstatus;
46 static volatile int rxstatus;
47 static volatile int rxactual;
48 
mdebug_notify(udc_gadget_t * gadget,unsigned event)49 static void mdebug_notify(udc_gadget_t *gadget, unsigned event) {
50     if (event == UDC_EVENT_ONLINE) {
51         online = 1;
52     } else {
53         online = 0;
54     }
55 }
56 
rx_complete(udc_request_t * req,unsigned actual,int status)57 static void rx_complete(udc_request_t *req, unsigned actual, int status) {
58     rxactual = actual;
59     rxstatus = status;
60     event_signal(&rxevt, 0);
61 }
62 
tx_complete(udc_request_t * req,unsigned actual,int status)63 static void tx_complete(udc_request_t *req, unsigned actual, int status) {
64     txstatus = status;
65     event_signal(&txevt, 0);
66 }
67 
68 #if TX_AHEAD
usb_xmit(void * data,unsigned len)69 void usb_xmit(void *data, unsigned len) {
70     event_wait(&txevt);
71     event_unsignal(&txevt);
72     txreq->buffer = data;
73     txreq->length = len;
74     txstatus = 1;
75     if (udc_request_queue(txept, txreq)) {
76         printf("txqf\n");
77         event_signal(&txevt, 0);
78     }
79 }
80 #else
usb_xmit(void * data,unsigned len)81 void usb_xmit(void *data, unsigned len) {
82     event_unsignal(&txevt);
83     txreq->buffer = data;
84     txreq->length = len;
85     txstatus = 1;
86     if (udc_request_queue(txept, txreq) == 0) {
87         event_wait(&txevt);
88     }
89 }
90 #endif
91 
usb_recv(void * data,unsigned len)92 int usb_recv(void *data, unsigned len) {
93     event_unsignal(&rxevt);
94     rxreq->buffer = data;
95     rxreq->length = len;
96     rxstatus = 1;
97     if (udc_request_queue(rxept, rxreq)) {
98         printf("rxqf\n");
99         return -1;
100     }
101     event_wait(&rxevt);
102     return rxstatus ? rxstatus : rxactual;
103 }
104 
105 static udc_device_t mdebug_device = {
106     .vendor_id = 0x1209,
107     .product_id = 0x5038,
108     .version_id = 0x0100,
109 };
110 
111 static udc_endpoint_t *mdebug_endpoints[2];
112 
113 static udc_gadget_t mdebug_gadget = {
114     .notify = mdebug_notify,
115     .ifc_class = 0xFF,
116     .ifc_subclass = 0xFF,
117     .ifc_protocol = 0xFF,
118     .ifc_endpoints = 2,
119     .ept = mdebug_endpoints,
120 };
121 
mdebug_init(const struct app_descriptor * app)122 static void mdebug_init(const struct app_descriptor *app) {
123     swd_init();
124 
125     udc_init(&mdebug_device);
126     mdebug_endpoints[0] = txept = udc_endpoint_alloc(UDC_BULK_IN, 512);
127     mdebug_endpoints[1] = rxept = udc_endpoint_alloc(UDC_BULK_OUT, 512);
128     txreq = udc_request_alloc();
129     rxreq = udc_request_alloc();
130     rxreq->complete = rx_complete;
131     txreq->complete = tx_complete;
132     udc_register_gadget(&mdebug_gadget);
133 }
134 
135 void handle_rswd(void);
136 void swo_init(udc_endpoint_t *ept);
137 void swo_config(unsigned mhz);
138 
mdebug_entry(const struct app_descriptor * app,void * args)139 static void mdebug_entry(const struct app_descriptor *app, void *args) {
140     udc_start();
141     swo_init(txept);
142     swo_config(6000000);
143 
144     for (;;) {
145         if (!online) {
146             thread_yield();
147             continue;
148         }
149         handle_rswd();
150     }
151 }
152 
153 APP_START(usbtest)
154 .init = mdebug_init,
155 .entry = mdebug_entry,
156 APP_END
157 
158 
159