Skip to content

Commit 7cc3816

Browse files
committed
feat(cdc): add a 1200 bps touch hook
The Arduino convention for asking a board to reboot into its bootloader is for the host to set the CDC line coding to 1200 bps and then close the port. The core tracks both halves already, in linecoding.bitrate and dtrState, but nothing acts on the combination, so a sketch has to poll Serial.baud() and Serial.dtr() from loop() and misses the event whenever loop() is busy. Add cdc_1200bps_touchHook(), a weak no-op alongside yield() and dtr_togglingHook(), called from CDC_SET_CONTROL_LINE_STATE when the port is closed at 1200 bps. dtr_togglingHook() cannot serve here because it is invoked from USBD_CDC_Receive and so requires the host to send data, which a 1200 bps touch does not. The hook only reports the event. It adds no series specific code, no backup register use and no policy about which bootloader to enter, so boards and sketches remain free to decide that. Refs #706, #710
1 parent 4ee32c3 commit 7cc3816

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

cores/arduino/hooks.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,26 @@ static void __empty_dtr_toggling(uint8_t *buf, uint32_t *len)
4949
(void)len;
5050
}
5151
void dtr_togglingHook(uint8_t *buf, uint32_t *len) __attribute__((weak, alias("__empty_dtr_toggling")));
52-
#endif
52+
#endif
53+
54+
#if defined(USBCON) && defined(USBD_USE_CDC)
55+
/**
56+
* Empty cdc_1200bps_touch() hook.
57+
*
58+
* Called when the host closes the CDC port while the line coding is set to
59+
* 1200 bps, which is the Arduino convention for asking the board to reboot
60+
* into its bootloader.
61+
*
62+
* Its defined as a weak symbol and it can be redefined to implement the
63+
* bootloader entry a given board needs.
64+
*
65+
* It is called from the USB control transfer callback, so it runs in handler
66+
* mode. Branching to a bootloader from here leaves the core inside an
67+
* exception that never returns; schedule the work and perform it from thread
68+
* mode or after a reset instead.
69+
*/
70+
static void __empty_1200bps_touch(void)
71+
{
72+
}
73+
void cdc_1200bps_touchHook(void) __attribute__((weak, alias("__empty_1200bps_touch")));
74+
#endif /* USBCON && USBD_USE_CDC */

libraries/USBDevice/src/cdc/usbd_cdc_if.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ __IO bool rtsState = false;
6060
__IO bool receivePended = true;
6161
static uint32_t transmitStart = 0;
6262

63+
extern void cdc_1200bps_touchHook(void);
64+
6365
#ifdef DTR_TOGGLING_SEQ
6466
/* DTR toggling sequence management */
6567
extern void dtr_togglingHook(uint8_t *buf, uint32_t *len);
@@ -195,6 +197,11 @@ static int8_t USBD_CDC_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length)
195197
transmitStart = 0;
196198
}
197199
rtsState = (((USBD_SetupReqTypedef *)pbuf)->wValue & CLS_RTS);
200+
/* Host closing the port at 1200 bps is the Arduino convention for
201+
requesting a reboot into the bootloader. */
202+
if (!dtrState && linecoding.bitrate == 1200) {
203+
cdc_1200bps_touchHook();
204+
}
198205
#ifdef DTR_TOGGLING_SEQ
199206
dtr_toggling++; /* Count DTR toggling */
200207
#endif

0 commit comments

Comments
 (0)