8000 Add support for Arduino boards jump to bootloader via CDC. by iabdalkader · Pull Request #8574 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content

Add support for Arduino boards jump to bootloader via CDC. #8574

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ports/nrf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ SRC_LIB += $(addprefix shared/,\
runtime/pyexec.c \
runtime/sys_stdio_mphal.c \
runtime/interrupt_char.c \
runtime/tinyusb_helpers.c \
timeutils/timeutils.c \
)

Expand Down
52 changes: 25 additions & 27 deletions ports/nrf/drivers/usb/usb_cdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ static volatile ringbuf_t tx_ringbuf;

static void board_init(void) {
// Config clock source.
#ifndef BLUETOOTH_SD
#ifndef BLUETOOTH_SD
NRF_CLOCK->LFCLKSRC = (uint32_t)((CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk);
NRF_CLOCK->TASKS_LFCLKSTART = 1UL;
#endif
#endif

// Priorities 0, 1, 4 (nRF52) are reserved for SoftDevice
// 2 is highest for application
Expand All @@ -66,7 +66,7 @@ static void board_init(void) {
// We need to invoke the handler based on the status initially
uint32_t usb_reg;

#ifdef BLUETOOTH_SD
#ifdef BLUETOOTH_SD
uint8_t sd_en = false;
sd_softdevice_is_enabled(&sd_en);

Expand All @@ -77,14 +77,14 @@ static void board_init(void) {

sd_power_usbregstatus_get(&usb_reg);
} else
#endif
#endif
{
// Power module init
const nrfx_power_config_t pwr_cfg = { 0 };
nrfx_power_init(&pwr_cfg);

// Register tusb function as USB power handler
const nrfx_power_usbevt_config_t config = { .handler = (nrfx_power_usb_event_handler_t) tusb_hal_nrf_power_event };
const nrfx_power_usbevt_config_t config = { .handler = (nrfx_power_usb_event_handler_t)tusb_hal_nrf_power_event };
nrfx_power_usbevt_init(&config);

nrfx_power_usbevt_enable();
Expand All @@ -96,48 +96,47 @@ static vo 8000 id board_init(void) {
tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_DETECTED);
}

#ifndef BLUETOOTH_SD
#ifndef BLUETOOTH_SD
if (usb_reg & POWER_USBREGSTATUS_OUTPUTRDY_Msk) {
tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY);
}
#endif
#endif
}

static bool cdc_rx_any(void) {
return rx_ringbuf.iput != rx_ringbuf.iget;
}

static int cdc_rx_char(void) {
return ringbuf_get((ringbuf_t*)&rx_ringbuf);
return ringbuf_get((ringbuf_t *)&rx_ringbuf);
}

static bool cdc_tx_any(void) {
return tx_ringbuf.iput != tx_ringbuf.iget;
}

static int cdc_tx_char(void) {
return ringbuf_get((ringbuf_t*)&tx_ringbuf);
return ringbuf_get((ringbuf_t *)&tx_ringbuf);
}

static void cdc_task(void)
{
if ( tud_cdc_connected() ) {
static void cdc_task(void) {
if (tud_cdc_connected()) {
// connected and there are data available
while (tud_cdc_available()) {
int c;
uint32_t count = tud_cdc_read(&c, 1);
(void)count;
ringbuf_put((ringbuf_t*)&rx_ringbuf, c);
ringbuf_put((ringbuf_t *)&rx_ringbuf, c);
}

int chars = 0;
while (cdc_tx_any()) {
if (chars < 64) {
tud_cdc_write_char(cdc_tx_char());
chars++;
tud_cdc_write_char(cdc_tx_char());
chars++;
8000 } else {
chars = 0;
tud_cdc_write_flush();
chars = 0;
tud_cdc_write_flush();
}
}

Expand All @@ -150,15 +149,14 @@ static void usb_cdc_loop(void) {
cdc_task();
}

int usb_cdc_init(void)
{
int usb_cdc_init(void) {
static bool initialized = false;
if (!initialized) {

#if BLUETOOTH_SD
#if BLUETOOTH_SD
// Initialize the clock and BLE stack.
ble_drv_stack_enable();
#endif
#endif

board_init();
initialized = true;
Expand All @@ -183,9 +181,9 @@ int usb_cdc_init(void)
// process SOC event from SD
void usb_cdc_sd_event_handler(uint32_t soc_evt) {
/*------------- usb power event handler -------------*/
int32_t usbevt = (soc_evt == NRF_EVT_POWER_USB_DETECTED ) ? NRFX_POWER_USB_EVT_DETECTED:
(soc_evt == NRF_EVT_POWER_USB_POWER_READY) ? NRFX_POWER_USB_EVT_READY :
(soc_evt == NRF_EVT_POWER_USB_REMOVED ) ? NRFX_POWER_USB_EVT_REMOVED : -1;
int32_t usbevt = (soc_evt == NRF_EVT_POWER_USB_DETECTED) ? NRFX_POWER_USB_EVT_DETECTED:
(soc_evt == NRF_EVT_POWER_USB_POWER_READY) ? NRFX_POWER_USB_EVT_READY :
(soc_evt == NRF_EVT_POWER_USB_REMOVED) ? NRFX_POWER_USB_EVT_REMOVED : -1;

if (usbevt >= 0) {
tusb_hal_nrf_power_event(usbevt);
Expand Down Expand Up @@ -219,7 +217,7 @@ int mp_hal_stdin_rx_chr(void) {
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {

for (const char *top = str + len; str < top; str++) {
ringbuf_put((ringbuf_t*)&tx_ringbuf, *str);
ringbuf_put((ringbuf_t *)&tx_ringbuf, *str);
usb_cdc_loop();
}
}
Expand All @@ -228,10 +226,10 @@ void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) {

for (const char *top = str + len; str < top; str++) {
if (*str == '\n') {
ringbuf_put((ringbuf_t*)&tx_ringbuf, '\r');
ringbuf_put((ringbuf_t *)&tx_ringbuf, '\r');
usb_cdc_loop();
}
ringbuf_put((ringbuf_t*)&tx_ringbuf, *str);
ringbuf_put((ringbuf_t *)&tx_ringbuf, *str);
usb_cdc_loop();
}
}
Expand Down
4 changes: 4 additions & 0 deletions ports/nrf/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_USE_INTERNAL_ERRNO (1)
#if MICROPY_HW_USB_CDC_1200BPS_TOUCH
#define MICROPY_ENABLE_SCHEDULER (1)
#define MICROPY_SCHEDULER_STATIC_NODES (1)
#endif
#define MICROPY_PY_FUNCTION_ATTRS (1)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
Expand Down
1 change: 1 addition & 0 deletions ports/rp2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ set(MICROPY_SOURCE_LIB
${MICROPY_DIR}/shared/runtime/pyexec.c
${MICROPY_DIR}/shared/runtime/stdout_helpers.c
${MICROPY_DIR}/shared/runtime/sys_stdio_mphal.c
${MICROPY_DIR}/shared/runtime/tinyusb_helpers.c
${MICROPY_DIR}/shared/timeutils/timeutils.c
)

Expand Down
1 change: 1 addition & 0 deletions ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define MICROPY_HW_USB_MSC (1)
#define MICROPY_HW_USB_VID (0x2341)
#define MICROPY_HW_USB_PID (0x025e)
#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1)

// UART 1 config.
#define MICROPY_HW_UART1_TX (8)
Expand Down
37 changes: 23 additions & 14 deletions ports/stm32/usbd_cdc_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@
#include "usbd_cdc_interface.h"
#include "pendsv.h"

#include "py/obj.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "shared/runtime/interrupt_char.h"
#include "irq.h"
#include "modmachine.h"

#if MICROPY_HW_ENABLE_USB

Expand All @@ -62,6 +64,14 @@
// Used to control the connect_state variable when USB host opens the serial port
static uint8_t usbd_cdc_connect_tx_timer;

#if MICROPY_HW_USB_CDC_1200BPS_TOUCH
static mp_sched_node_t mp_bootloader_sched_node;
STATIC void usbd_cdc_run_bootloader_task(mp_sched_node_t *node) {
mp_hal_delay_ms(250);
machine_bootloader(0, NULL);
}
#endif

uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) {
usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t *)cdc_in;

Expand All @@ -81,6 +91,7 @@ uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) {
} else {
cdc->flow |= USBD_CDC_FLOWCONTROL_CTS;
}
cdc->bitrate = 0;

// Return the buffer to place the first USB OUT packet
return cdc->rx_packet_buf;
Expand Down Expand Up @@ -121,22 +132,14 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t *pbuf, ui
break;

case CDC_SET_LINE_CODING:
#if 0
LineCoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) | \
(pbuf[2] << 16) | (pbuf[3] << 24));
LineCoding.format = pbuf[4];
LineCoding.paritytype = pbuf[5];
LineCoding.datatype = pbuf[6];
/* Set the new configuration */
#endif
cdc->bitrate = *((uint32_t *)pbuf);
break;

case CDC_GET_LINE_CODING:
/* Add your code here */
pbuf[0] = (uint8_t)(115200);
pbuf[1] = (uint8_t)(115200 >> 8);
pbuf[2] = (uint8_t)(115200 >> 16);
pbuf[3] = (uint8_t)(115200 >> 24);
pbuf[0] = (uint8_t)(cdc->bitrate);
pbuf[1] = (uint8_t)(cdc->bitrate >> 8);
pbuf[2] = (uint8_t)(cdc->bitrate >> 16);
pbuf[3] = (uint8_t)(cdc->bitrate >> 24);
pbuf[4] = 0; // stop bits (1)
pbuf[5] = 0; // parity (none)
pbuf[6] = 8; // number of bits (8)
Expand All @@ -157,6 +160,12 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t *pbuf, ui
#endif
} else {
cdc->connect_state = USBD_CDC_CONNECT_STATE_DISCONNECTED;
#if MICROPY_HW_USB_CDC_1200BPS_TOUCH
if (cdc->bitrate == 1200) {
// Delay bootloader jump to allow the USB stack to service endpoints.
mp_sched_schedule_node(&mp_bootloader_sched_node, usbd_cdc_run_bootloader_task);
}
#endif
}
break;
}
Expand Down
1 change: 1 addition & 0 deletions ports/stm32/usbd_cdc_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ typedef struct _usbd_cdc_itf_t {
volatile uint8_t connect_state; // indicates if we are connected
uint8_t attached_to_repl; // indicates if interface is connected to REPL
uint8_t flow; // USBD_CDC_FLOWCONTROL_* setting flags
uint32_t bitrate;
} usbd_cdc_itf_t;

// This is implemented in usb.c
Expand Down
52 changes: 52 additions & 0 deletions shared/runtime/tinyusb_helpers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Ibrahim Abdelkader <iabdalkader@openmv.io>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/

#include "py/runtime.h"
#include "py/mphal.h"
#include "modmachine.h"

#if MICROPY_HW_USB_CDC_1200BPS_TOUCH
#include "tusb.h"

static mp_sched_node_t mp_bootloader_sched_node;
STATIC void usbd_cdc_run_bootloader_task(mp_sched_node_t *node) {
mp_hal_delay_ms(250);
machine_bootloader(0, NULL);
}

void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
if (dtr == false && rts == false) {
// Device is disconnected.
cdc_line_coding_t line_coding;
tud_cdc_n_get_line_coding(itf, &line_coding);
if (line_coding.bit_rate == 1200) {
// Delay bootloader jump to allow the USB stack to service endpoints.
mp_sched_schedule_node(&mp_bootloader_sched_node, usbd_cdc_run_bootloader_task);
}
}
}
#endif
0