Skip to content

Commit 39faaf7

Browse files
committed
enhancement to HardwareSerial (requires minor update to pins_ardino.h files)
ongoing effort on USB support. ongoing effort on E5 PWM fixes. bootloader improvements for 'wiring' protocol, and a bit of cleanup.
1 parent db9eef8 commit 39faaf7

File tree

17 files changed

+2727
-1448
lines changed

17 files changed

+2727
-1448
lines changed

bootloaders/xmega/xmegaBOOT.c

+505-452
Large diffs are not rendered by default.

cores/xmega/CDC.cpp

+142-112
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525

2626
typedef struct
2727
{
28-
u32 dwDTERate;
29-
u8 bCharFormat;
30-
u8 bParityType;
31-
u8 bDataBits;
32-
u8 lineState;
28+
u32 dwDTERate;
29+
u8 bCharFormat;
30+
u8 bParityType;
31+
u8 bDataBits;
32+
u8 lineState;
3333
} LineInfo;
3434

3535
static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
@@ -39,89 +39,107 @@ static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
3939
extern const CDCDescriptor _cdcInterface PROGMEM;
4040
const CDCDescriptor _cdcInterface =
4141
{
42-
D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1),
43-
44-
// CDC communication interface
45-
D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),
46-
D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd)
47-
D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not)
48-
D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
49-
D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
50-
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40),
51-
52-
// CDC data interface
53-
D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0),
54-
D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0),
55-
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0)
42+
D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1),
43+
44+
// CDC communication interface
45+
D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),
46+
D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd)
47+
D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not)
48+
D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
49+
D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
50+
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40),
51+
52+
// CDC data interface
53+
D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0),
54+
D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0),
55+
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0)
5656
};
5757

5858
int WEAK CDC_GetInterface(u8* interfaceNum)
5959
{
60-
interfaceNum[0] += 2; // uses 2
61-
return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface));
60+
interfaceNum[0] += 2; // uses 2
61+
return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface));
6262
}
6363

6464
bool WEAK CDC_Setup(Setup& setup)
6565
{
66-
u8 r = setup.bRequest;
67-
u8 requestType = setup.bmRequestType;
68-
69-
if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
70-
{
71-
if (CDC_GET_LINE_CODING == r)
72-
{
73-
USB_SendControl(0,(void*)&_usbLineInfo,7);
74-
return true;
75-
}
76-
}
77-
78-
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
79-
{
80-
if (CDC_SET_LINE_CODING == r)
81-
{
82-
USB_RecvControl((void*)&_usbLineInfo,7);
83-
return true;
84-
}
85-
86-
if (CDC_SET_CONTROL_LINE_STATE == r)
87-
{
88-
_usbLineInfo.lineState = setup.wValueL;
89-
90-
// auto-reset into the bootloader is triggered when the port, already
91-
// open at 1200 bps, is closed. this is the signal to start the watchdog
92-
// with a relatively long period so it can finish housekeeping tasks
93-
// like servicing endpoints before the sketch ends
94-
if (1200 == _usbLineInfo.dwDTERate) {
95-
// We check DTR state to determine if host port is open (bit 0 of lineState).
96-
if ((_usbLineInfo.lineState & 0x01) == 0) {
97-
*(uint16_t *)0x0800 = 0x7777;
98-
wdt_enable(WDTO_120MS);
99-
} else {
100-
// Most OSs do some intermediate steps when configuring ports and DTR can
101-
// twiggle more than once before stabilizing.
102-
// To avoid spurious resets we set the watchdog to 250ms and eventually
103-
// cancel if DTR goes back high.
104-
105-
wdt_disable();
106-
wdt_reset();
107-
*(uint16_t *)0x0800 = 0x0;
108-
}
109-
}
110-
return true;
111-
}
112-
}
113-
return false;
66+
u8 r = setup.bRequest;
67+
u8 requestType = setup.bmRequestType;
68+
69+
if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
70+
{
71+
if (CDC_GET_LINE_CODING == r)
72+
{
73+
#if 1
74+
USB_SendControl(0,(void*)&_usbLineInfo,7);
75+
#endif // 0
76+
return true;
77+
}
78+
}
79+
80+
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
81+
{
82+
if (CDC_SET_LINE_CODING == r)
83+
{
84+
#if 1
85+
USB_RecvControl((void*)&_usbLineInfo,7);
86+
#endif // 0
87+
return true;
88+
}
89+
// NOTE: this next part is for the 'caterina' CDC bootloader, arduino/bootloaders/caterina/Caterina.c
90+
// it has some "special" code in it, like using 0x0800 in RAM as an address for a 'key' (7777H)
91+
// to indicate it was soft-booted. XMEGA has better ways of handling this, like a CPU flag that
92+
// indicates "I was soft-booted" as one example, and a 'WDT' timeout flag on top of that.
93+
if (CDC_SET_CONTROL_LINE_STATE == r)
94+
{
95+
_usbLineInfo.lineState = setup.wValueL;
96+
97+
// auto-reset into the bootloader is triggered when the port, already
98+
// open at 1200 bps, is closed. this is the signal to start the watchdog
99+
// with a relatively long period so it can finish housekeeping tasks
100+
// like servicing endpoints before the sketch ends
101+
if (1200 == _usbLineInfo.dwDTERate)
102+
{
103+
// We check DTR state to determine if host port is open (bit 0 of lineState).
104+
if ((_usbLineInfo.lineState & 0x01) == 0)
105+
{
106+
// This section of code is support for the 'caterina' bootloader, which allows USB flashing (apparently)
107+
//
108+
// *(uint16_t *)0x0800 = 0x7777; note that on XMEGA this is a VERY bad thing
109+
// wdt_enable(WDTO_120MS);
110+
111+
// TODO: timeout-based reboot
112+
}
113+
else // 3 lines better than 1 - ALLMAN STYLE! - do *NOT* do '} else {' - BLEAH!
114+
{
115+
// Most OSs do some intermediate steps when configuring ports and DTR can
116+
// twiggle more than once before stabilizing.
117+
// To avoid spurious resets we set the watchdog to 250ms and eventually
118+
// cancel if DTR goes back high.
119+
120+
// This section of code is support for the 'caterina' bootloader, which allows USB flashing (apparently)
121+
//
122+
// TODO: reset whatever boot timeout I did
123+
// wdt_disable();
124+
// wdt_reset();
125+
// *(uint16_t *)0x0800 = 0x0; note that on XMEGA this is a VERY bad thing
126+
}
127+
}
128+
return true;
129+
}
130+
}
131+
return false;
114132
}
115133

116134

117135
void Serial_::begin(unsigned long baud_count)
118136
{
119-
peek_buffer = -1;
137+
peek_buffer = -1;
120138
}
121139

122140
void Serial_::begin(unsigned long baud_count, byte config)
123141
{
124-
peek_buffer = -1;
142+
peek_buffer = -1;
125143
}
126144

127145
void Serial_::end(void)
@@ -130,61 +148,69 @@ void Serial_::end(void)
130148

131149
int Serial_::available(void)
132150
{
133-
if (peek_buffer >= 0) {
134-
return 1 + USB_Available(CDC_RX);
135-
}
136-
return USB_Available(CDC_RX);
151+
if (peek_buffer >= 0)
152+
{
153+
return 1 + USB_Available(CDC_RX);
154+
}
155+
return USB_Available(CDC_RX);
137156
}
138157

139158
int Serial_::peek(void)
140159
{
141-
if (peek_buffer < 0)
142-
peek_buffer = USB_Recv(CDC_RX);
143-
return peek_buffer;
160+
if (peek_buffer < 0)
161+
{
162+
peek_buffer = USB_Recv(CDC_RX);
163+
}
164+
return peek_buffer;
144165
}
145166

146167
int Serial_::read(void)
147168
{
148-
if (peek_buffer >= 0) {
149-
int c = peek_buffer;
150-
peek_buffer = -1;
151-
return c;
152-
}
153-
return USB_Recv(CDC_RX);
169+
if (peek_buffer >= 0)
170+
{
171+
int c = peek_buffer;
172+
peek_buffer = -1;
173+
return c;
174+
}
175+
return USB_Recv(CDC_RX);
154176
}
155177

156178
void Serial_::flush(void)
157179
{
158-
USB_Flush(CDC_TX);
180+
USB_Flush(CDC_TX);
159181
}
160182

161183
size_t Serial_::write(uint8_t c)
162184
{
163-
return write(&c, 1);
185+
return write(&c, 1);
164186
}
165187

166188
size_t Serial_::write(const uint8_t *buffer, size_t size)
167189
{
168-
/* only try to send bytes if the high-level CDC connection itself
169-
is open (not just the pipe) - the OS should set lineState when the port
170-
is opened and clear lineState when the port is closed.
171-
bytes sent before the user opens the connection or after
172-
the connection is closed are lost - just like with a UART. */
173-
174-
// TODO - ZE - check behavior on different OSes and test what happens if an
175-
// open connection isn't broken cleanly (cable is yanked out, host dies
176-
// or locks up, or host virtual serial port hangs)
177-
if (_usbLineInfo.lineState > 0) {
178-
int r = USB_Send(CDC_TX,buffer,size);
179-
if (r > 0) {
180-
return r;
181-
} else {
182-
setWriteError();
183-
return 0;
184-
}
185-
}
186-
setWriteError();
187-
return 0;
190+
/* only try to send bytes if the high-level CDC connection itself
191+
is open (not just the pipe) - the OS should set lineState when the port
192+
is opened and clear lineState when the port is closed.
193+
bytes sent before the user opens the connection or after
194+
the connection is closed are lost - just like with a UART. */
195+
196+
// TODO - ZE - check behavior on different OSes and test what happens if an
197+
// open connection isn't broken cleanly (cable is yanked out, host dies
198+
// or locks up, or host virtual serial port hangs)
199+
if (_usbLineInfo.lineState > 0)
200+
{
201+
int r = USB_Send(CDC_TX,buffer,size);
202+
if (r > 0)
203+
{
204+
return r;
205+
}
206+
else
207+
{
208+
setWriteError();
209+
return 0;
210+
}
211+
}
212+
setWriteError();
213+
return 0;
188214
}
189215

190216
// This operator is a convenient way for a sketch to check whether the
@@ -194,15 +220,19 @@ size_t Serial_::write(const uint8_t *buffer, size_t size)
194220
// actually ready to receive and display the data.
195221
// We add a short delay before returning to fix a bug observed by Federico
196222
// where the port is configured (lineState != 0) but not quite opened.
197-
Serial_::operator bool() {
198-
bool result = false;
199-
if (_usbLineInfo.lineState > 0)
200-
result = true;
201-
delay(10);
202-
return result;
223+
Serial_::operator bool()
224+
{
225+
bool result = false;
226+
if (_usbLineInfo.lineState > 0)
227+
{
228+
result = true;
229+
}
230+
delay(10);
231+
return result;
203232
}
204233

205234
Serial_ Serial;
206235

207236
#endif
208237
#endif /* if defined(USBCON) */
238+

0 commit comments

Comments
 (0)