Browse Source

nrf: Consolidate all stdio functions.

Consolidate CDC, UART and NUS stdio interfaces into the one handler.
Allows any/all of them to be enabled separately.

Updates UART REPL to use similar define to other platforms:
`MICROPY_HW_ENABLE_UART_REPL`.

USB now uses the shared/tinyusb CDC implementation.

Signed-off-by: Andrew Leech <andrew@alelec.net>
pull/15158/head
Andrew Leech 5 months ago
committed by Damien George
parent
commit
19075695da
  1. 25
      ports/nrf/Makefile
  2. 13
      ports/nrf/bluetooth_conf.h
  3. 1
      ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.h
  4. 4
      ports/nrf/boards/PCA10056/mpconfigboard.h
  5. 4
      ports/nrf/boards/PCA10059/mpconfigboard.mk
  6. 1
      ports/nrf/boards/SEEED_XIAO_NRF52/mpconfigboard.h
  7. 4
      ports/nrf/drivers/bluetooth/ble_drv.c
  8. 29
      ports/nrf/drivers/bluetooth/ble_uart.c
  9. 4
      ports/nrf/drivers/bluetooth/ble_uart.h
  10. 14
      ports/nrf/drivers/usb/tusb_config.h
  11. 136
      ports/nrf/drivers/usb/usb_cdc.c
  12. 117
      ports/nrf/drivers/usb/usb_descriptors.c
  13. 10
      ports/nrf/main.c
  14. 39
      ports/nrf/mpconfigport.h
  15. 86
      ports/nrf/mphalport.c
  16. 4
      ports/nrf/mphalport.h

25
ports/nrf/Makefile

@ -80,15 +80,16 @@ INC += -I./modules/music
INC += -I./modules/ble INC += -I./modules/ble
INC += -I./modules/board INC += -I./modules/board
INC += -I./modules/nrf INC += -I./modules/nrf
INC += -I../../shared/readline
INC += -I./drivers/bluetooth
INC += -I./drivers INC += -I./drivers
INC += -I./drivers/bluetooth
INC += -I./drivers/usb
INC += -I../../lib/nrfx/ INC += -I../../lib/nrfx/
INC += -I../../lib/nrfx/drivers INC += -I../../lib/nrfx/drivers
INC += -I../../lib/nrfx/drivers/include INC += -I../../lib/nrfx/drivers/include
INC += -I../../lib/nrfx/mdk INC += -I../../lib/nrfx/mdk
INC += -I../../lib/nrfx/hal INC += -I../../lib/nrfx/hal
INC += -I../../lib/nrfx/drivers/src/ INC += -I../../lib/nrfx/drivers/src/
INC += -I../../shared/readline
MCU_VARIANT_UPPER = $(shell echo $(MCU_VARIANT) | tr '[:lower:]' '[:upper:]') MCU_VARIANT_UPPER = $(shell echo $(MCU_VARIANT) | tr '[:lower:]' '[:upper:]')
MCU_SUB_VARIANT_UPPER = $(shell echo $(MCU_SUB_VARIANT) | tr '[:lower:]' '[:upper:]') MCU_SUB_VARIANT_UPPER = $(shell echo $(MCU_SUB_VARIANT) | tr '[:lower:]' '[:upper:]')
@ -183,9 +184,12 @@ SRC_SHARED_C += $(addprefix shared/,\
libc/string0.c \ libc/string0.c \
readline/readline.c \ readline/readline.c \
runtime/pyexec.c \ runtime/pyexec.c \
runtime/stdout_helpers.c \
runtime/sys_stdio_mphal.c \ runtime/sys_stdio_mphal.c \
runtime/interrupt_char.c \ runtime/interrupt_char.c \
tinyusb/mp_usbd.c \
tinyusb/mp_usbd_cdc.c \ tinyusb/mp_usbd_cdc.c \
tinyusb/mp_usbd_descriptor.c \
timeutils/timeutils.c \ timeutils/timeutils.c \
) )
@ -200,13 +204,13 @@ endif
SRC_NRFX += $(addprefix lib/nrfx/drivers/src/,\ SRC_NRFX += $(addprefix lib/nrfx/drivers/src/,\
prs/nrfx_prs.c \ prs/nrfx_prs.c \
nrfx_uart.c \ nrfx_uart.c \
nrfx_uarte.c \ nrfx_uarte.c \
nrfx_adc.c \ nrfx_adc.c \
nrfx_saadc.c \ nrfx_saadc.c \
nrfx_temp.c \ nrfx_temp.c \
nrfx_rng.c \ nrfx_rng.c \
nrfx_twi.c \ nrfx_twi.c \
nrfx_twim.c \ nrfx_twim.c \
nrfx_spi.c \ nrfx_spi.c \
nrfx_spim.c \ nrfx_spim.c \
nrfx_rtc.c \ nrfx_rtc.c \
@ -234,21 +238,17 @@ SRC_C += \
$(wildcard $(BOARD_DIR)/*.c) \ $(wildcard $(BOARD_DIR)/*.c) \
ifeq ($(MCU_SUB_VARIANT), nrf52840) ifeq ($(MCU_SUB_VARIANT), nrf52840)
# Add support for USB using TinyUSB.
INC += -I./drivers/usb
INC += -I../../lib/tinyusb/src INC += -I../../lib/tinyusb/src
# If SoftDevice is selected. # If SoftDevice is selected.
ifneq ($(SD), ) ifneq ($(SD), )
# For external tinyusb drivers to enable SoftDevice mode. # For external tinyusb drivers to enable SoftDevice mode.
CFLAGS += -DSOFTDEVICE_PRESENT CFLAGS += -DSOFTDEVICE_PRESENT
endif endif
SRC_C += $(addprefix drivers/usb/,\ SRC_C += drivers/usb/usb_cdc.c
usb_cdc.c \
usb_descriptors.c \
)
SRC_C += $(addprefix lib/tinyusb/src/,\ SRC_C += $(addprefix lib/tinyusb/src/,\
common/tusb_fifo.c \ common/tusb_fifo.c \
@ -259,6 +259,7 @@ SRC_C += $(addprefix lib/tinyusb/src/,\
portable/nordic/nrf5x/dcd_nrf5x.c \ portable/nordic/nrf5x/dcd_nrf5x.c \
) )
LDFLAGS += -Wl,--wrap=dcd_event_handler
endif endif
DRIVERS_SRC_C += $(addprefix modules/,\ DRIVERS_SRC_C += $(addprefix modules/,\
@ -331,9 +332,9 @@ hex: $(BUILD)/$(OUTPUT_FILENAME).hex
$(BUILD)/$(OUTPUT_FILENAME).hex: $(BUILD)/$(OUTPUT_FILENAME).elf $(BUILD)/$(OUTPUT_FILENAME).hex: $(BUILD)/$(OUTPUT_FILENAME).elf
$(OBJCOPY) -O ihex $< $@ $(OBJCOPY) -O ihex $< $@
FLASHER ?= FLASHER ?= jlink
ifeq ($(FLASHER),) ifeq ($(FLASHER), jlink)
ifeq ($(MCU_VARIANT), nrf91) ifeq ($(MCU_VARIANT), nrf91)

13
ports/nrf/bluetooth_conf.h

@ -3,10 +3,15 @@
// SD specific configurations. // SD specific configurations.
#ifndef MICROPY_PY_BLE_NUS
// Nordic UART Service
// If enabled, REPL will be available on this interface.
#define MICROPY_PY_BLE_NUS (0)
#endif
#if (BLUETOOTH_SD == 110) #if (BLUETOOTH_SD == 110)
#define MICROPY_PY_BLE (1) #define MICROPY_PY_BLE (1)
#define MICROPY_PY_BLE_NUS (0)
#define BLUETOOTH_WEBBLUETOOTH_REPL (0) #define BLUETOOTH_WEBBLUETOOTH_REPL (0)
#define MICROPY_PY_UBLUEPY (1) #define MICROPY_PY_UBLUEPY (1)
#define MICROPY_PY_UBLUEPY_PERIPHERAL (1) #define MICROPY_PY_UBLUEPY_PERIPHERAL (1)
@ -14,7 +19,6 @@
#elif (BLUETOOTH_SD == 132) #elif (BLUETOOTH_SD == 132)
#define MICROPY_PY_BLE (1) #define MICROPY_PY_BLE (1)
#define MICROPY_PY_BLE_NUS (0)
#define BLUETOOTH_WEBBLUETOOTH_REPL (0) #define BLUETOOTH_WEBBLUETOOTH_REPL (0)
#define MICROPY_PY_UBLUEPY (1) #define MICROPY_PY_UBLUEPY (1)
#define MICROPY_PY_UBLUEPY_PERIPHERAL (1) #define MICROPY_PY_UBLUEPY_PERIPHERAL (1)
@ -23,7 +27,6 @@
#elif (BLUETOOTH_SD == 140) #elif (BLUETOOTH_SD == 140)
#define MICROPY_PY_BLE (1) #define MICROPY_PY_BLE (1)
#define MICROPY_PY_BLE_NUS (0)
#define BLUETOOTH_WEBBLUETOOTH_REPL (0) #define BLUETOOTH_WEBBLUETOOTH_REPL (0)
#define MICROPY_PY_UBLUEPY (1) #define MICROPY_PY_UBLUEPY (1)
#define MICROPY_PY_UBLUEPY_PERIPHERAL (1) #define MICROPY_PY_UBLUEPY_PERIPHERAL (1)
@ -39,8 +42,4 @@
#define MICROPY_PY_BLE (0) #define MICROPY_PY_BLE (0)
#endif #endif
#ifndef MICROPY_PY_BLE_NUS
#define MICROPY_PY_BLE_NUS (0)
#endif
#endif #endif

1
ports/nrf/boards/ARDUINO_NANO_33_BLE_SENSE/mpconfigboard.h

@ -18,6 +18,7 @@
#define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_ADC (1)
#define MICROPY_PY_MACHINE_TEMP (1) #define MICROPY_PY_MACHINE_TEMP (1)
#define MICROPY_HW_ENABLE_USBDEV (1)
#define MICROPY_HW_USB_CDC (1) #define MICROPY_HW_USB_CDC (1)
#define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_HAS_LED (1)
#define MICROPY_HW_HAS_SWITCH (0) #define MICROPY_HW_HAS_SWITCH (0)

4
ports/nrf/boards/PCA10056/mpconfigboard.h

@ -37,6 +37,9 @@
#define MICROPY_HW_ENABLE_RNG (1) #define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_USBDEV (1)
#define MICROPY_HW_USB_CDC (1)
#define MICROPY_HW_HAS_LED (1) #define MICROPY_HW_HAS_LED (1)
#define MICROPY_HW_LED_COUNT (4) #define MICROPY_HW_LED_COUNT (4)
#define MICROPY_HW_LED_PULLUP (1) #define MICROPY_HW_LED_PULLUP (1)
@ -47,6 +50,7 @@
#define MICROPY_HW_LED4 (16) // LED4 #define MICROPY_HW_LED4 (16) // LED4
// UART config // UART config
#define MICROPY_HW_ENABLE_UART_REPL (1)
#define MICROPY_HW_UART1_RX (8) #define MICROPY_HW_UART1_RX (8)
#define MICROPY_HW_UART1_TX (6) #define MICROPY_HW_UART1_TX (6)
#define MICROPY_HW_UART1_CTS (7) #define MICROPY_HW_UART1_CTS (7)

4
ports/nrf/boards/PCA10059/mpconfigboard.mk

@ -9,9 +9,7 @@ ifeq ($(DFU),1)
BOOTLOADER=open_bootloader BOOTLOADER=open_bootloader
BOOTLOADER_VERSION_MAJOR=1 BOOTLOADER_VERSION_MAJOR=1
BOOTLOADER_VERSION_MINOR=2 BOOTLOADER_VERSION_MINOR=2
FLASHER=nrfutil FLASHER ?= nrfutil
else
FLASHER=segger
endif endif
LD_FILES += boards/nrf52840_1M_256k.ld LD_FILES += boards/nrf52840_1M_256k.ld

1
ports/nrf/boards/SEEED_XIAO_NRF52/mpconfigboard.h

@ -32,6 +32,7 @@
#define MICROPY_BOARD_DEINIT XIAO_board_deinit #define MICROPY_BOARD_DEINIT XIAO_board_deinit
#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) XIAO_board_enter_bootloader() #define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) XIAO_board_enter_bootloader()
#define MICROPY_HW_ENABLE_USBDEV (1)
#define MICROPY_HW_USB_CDC (1) #define MICROPY_HW_USB_CDC (1)
#define MICROPY_PY_MACHINE_UART (1) #define MICROPY_PY_MACHINE_UART (1)
#define MICROPY_PY_MACHINE_HW_PWM (1) #define MICROPY_PY_MACHINE_HW_PWM (1)

4
ports/nrf/drivers/bluetooth/ble_drv.c

@ -39,7 +39,7 @@
#include "mphalport.h" #include "mphalport.h"
#if MICROPY_HW_USB_CDC #if MICROPY_HW_ENABLE_USBDEV && MICROPY_HW_USB_CDC
#include "usb_cdc.h" #include "usb_cdc.h"
#endif #endif
@ -941,7 +941,7 @@ static void sd_evt_handler(uint32_t evt_id) {
// unhandled event! // unhandled event!
break; break;
} }
#if MICROPY_HW_USB_CDC #if MICROPY_HW_ENABLE_USBDEV && MICROPY_HW_USB_CDC
// Forward SOC events to USB CDC driver. // Forward SOC events to USB CDC driver.
usb_cdc_sd_event_handler(evt_id); usb_cdc_sd_event_handler(evt_id);
#endif #endif

29
ports/nrf/drivers/bluetooth/ble_uart.c

@ -97,20 +97,16 @@ static ubluepy_advertise_data_t m_adv_data_uart_service;
static ubluepy_advertise_data_t m_adv_data_eddystone_url; static ubluepy_advertise_data_t m_adv_data_eddystone_url;
#endif // BLUETOOTH_WEBBLUETOOTH_REPL #endif // BLUETOOTH_WEBBLUETOOTH_REPL
int mp_hal_stdin_rx_chr(void) { int mp_ble_uart_stdin_rx_chr(void) {
while (!ble_uart_enabled()) { if (ble_uart_enabled() && !isBufferEmpty(mp_rx_ring_buffer)) {
// wait for connection uint8_t byte = -1;
bufferRead(mp_rx_ring_buffer, byte);
return (int)byte;
} }
while (isBufferEmpty(mp_rx_ring_buffer)) { return -1;
;
}
uint8_t byte;
bufferRead(mp_rx_ring_buffer, byte);
return (int)byte;
} }
mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { mp_uint_t mp_ble_uart_stdout_tx_strn(const char *str, size_t len) {
// Not connected: drop output // Not connected: drop output
if (!ble_uart_enabled()) return 0; if (!ble_uart_enabled()) return 0;
@ -150,17 +146,8 @@ void ble_uart_tx_char(char c) {
(uint8_t *)&c); (uint8_t *)&c);
} }
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') {
ble_uart_tx_char('\r');
}
ble_uart_tx_char(*str);
}
}
#if MICROPY_PY_SYS_STDFILES #if MICROPY_PY_SYS_STDFILES
uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t mp_ble_uart_stdio_poll(uintptr_t poll_flags) {
uintptr_t ret = 0; uintptr_t ret = 0;
if ((poll_flags & MP_STREAM_POLL_RD) && ble_uart_enabled() if ((poll_flags & MP_STREAM_POLL_RD) && ble_uart_enabled()
&& !isBufferEmpty(mp_rx_ring_buffer)) { && !isBufferEmpty(mp_rx_ring_buffer)) {

4
ports/nrf/drivers/bluetooth/ble_uart.h

@ -37,6 +37,10 @@ void ble_uart_advertise(void);
bool ble_uart_connected(void); bool ble_uart_connected(void);
bool ble_uart_enabled(void); bool ble_uart_enabled(void);
uintptr_t mp_ble_uart_stdio_poll(uintptr_t poll_flags);
int mp_ble_uart_stdin_rx_chr(void);
mp_uint_t mp_ble_uart_stdout_tx_strn(const char *str, size_t len);
#endif // BLUETOOTH_SD #endif // BLUETOOTH_SD
#endif // BLUETOOTH_LE_UART_H__ #endif // BLUETOOTH_LE_UART_H__

14
ports/nrf/drivers/usb/tusb_config.h

@ -26,19 +26,9 @@
#ifndef MICROPY_INCLUDED_NRF_TUSB_CONFIG_H #ifndef MICROPY_INCLUDED_NRF_TUSB_CONFIG_H
#define MICROPY_INCLUDED_NRF_TUSB_CONFIG_H #define MICROPY_INCLUDED_NRF_TUSB_CONFIG_H
// Common configuration #include "shared/tinyusb/tusb_config.h"
#define CFG_TUSB_MCU OPT_MCU_NRF5X
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
#define CFG_TUSB_MEM_SECTION
#define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4)
// Device configuration // Device configuration
#define CFG_TUSB_MCU OPT_MCU_NRF5X
#define CFG_TUD_ENDOINT0_SIZE (64)
#define CFG_TUD_CDC (1)
#define CFG_TUD_CDC_RX_BUFSIZE (64)
#define CFG_TUD_CDC_TX_BUFSIZE (64)
#endif // MICROPY_INCLUDED_NRF_TUSB_CONFIG_H #endif // MICROPY_INCLUDED_NRF_TUSB_CONFIG_H

136
ports/nrf/drivers/usb/usb_cdc.c

@ -27,7 +27,7 @@
#include "py/mphal.h" #include "py/mphal.h"
#if MICROPY_HW_USB_CDC #if MICROPY_HW_ENABLE_USBDEV && MICROPY_HW_USB_CDC
#include "nrfx.h" #include "nrfx.h"
#include "nrfx_power.h" #include "nrfx_power.h"
@ -37,6 +37,9 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "shared/runtime/interrupt_char.h" #include "shared/runtime/interrupt_char.h"
#include "shared/tinyusb/mp_usbd.h" #include "shared/tinyusb/mp_usbd.h"
#include "shared/tinyusb/mp_usbd_cdc.h"
#include "extmod/misc.h"
#include <hal/nrf_ficr.h>
#ifdef BLUETOOTH_SD #ifdef BLUETOOTH_SD
#include "nrf_sdm.h" #include "nrf_sdm.h"
@ -46,13 +49,6 @@
extern void tusb_hal_nrf_power_event(uint32_t event); extern void tusb_hal_nrf_power_event(uint32_t event);
static void cdc_task(bool tx);
static uint8_t rx_ringbuf_array[1024];
static uint8_t tx_ringbuf_array[1024];
static volatile ringbuf_t rx_ringbuf;
static volatile ringbuf_t tx_ringbuf;
static void board_init(void) { static void board_init(void) {
// Config clock source. // Config clock source.
#ifndef BLUETOOTH_SD #ifndef BLUETOOTH_SD
@ -105,89 +101,27 @@ static void board_init(void) {
#endif #endif
} }
static bool cdc_rx_any(void) { void mp_usbd_port_get_serial_number(char *serial_buf) {
return rx_ringbuf.iput != rx_ringbuf.iget; uint32_t deviceid[2];
} deviceid[0] = nrf_ficr_deviceid_get(NRF_FICR, 0);
deviceid[1] = nrf_ficr_deviceid_get(NRF_FICR, 1);
static int cdc_rx_char(void) { MP_STATIC_ASSERT(sizeof(deviceid) * 2 <= MICROPY_HW_USB_DESC_STR_MAX);
return ringbuf_get((ringbuf_t*)&rx_ringbuf); mp_usbd_hex_str(serial_buf, (uint8_t *)deviceid, sizeof(deviceid));
}
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);
}
static void cdc_task(bool tx)
{
if ( tud_cdc_connected() ) {
// connected and there are data available
while (tud_cdc_available()) {
int c = tud_cdc_read_char();
if (c == mp_interrupt_char) {
rx_ringbuf.iget = 0;
rx_ringbuf.iput = 0;
mp_sched_keyboard_interrupt();
} else {
ringbuf_put((ringbuf_t*)&rx_ringbuf, c);
}
}
if (tx) {
int chars = 0;
while (cdc_tx_any()) {
if (chars < 64) {
tud_cdc_write_char(cdc_tx_char());
chars++;
} else {
chars = 0;
tud_cdc_write_flush();
}
}
tud_cdc_write_flush();
}
}
}
static void usb_cdc_loop(void) {
tud_task();
cdc_task(true);
}
void tud_cdc_rx_cb(uint8_t itf) {
cdc_task(false);
} }
int usb_cdc_init(void) int usb_cdc_init(void)
{ {
static bool initialized = false; static bool initialized = false;
if (!initialized) { if (!initialized) {
#if BLUETOOTH_SD
#if BLUETOOTH_SD
// Initialize the clock and BLE stack. // Initialize the clock and BLE stack.
ble_drv_stack_enable(); ble_drv_stack_enable();
#endif #endif
board_init(); board_init();
initialized = true; initialized = true;
} }
rx_ringbuf.buf = rx_ringbuf_array;
rx_ringbuf.size = sizeof(rx_ringbuf_array);
rx_ringbuf.iget = 0;
rx_ringbuf.iput = 0;
tx_ringbuf.buf = tx_ringbuf_array;
tx_ringbuf.size = sizeof(tx_ringbuf_array);
tx_ringbuf.iget = 0;
tx_ringbuf.iput = 0;
mp_usbd_init(); mp_usbd_init();
return 0; return 0;
} }
@ -205,52 +139,6 @@ void usb_cdc_sd_event_handler(uint32_t soc_evt) {
} }
#endif #endif
uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
uintptr_t ret = 0;
if (poll_flags & MP_STREAM_POLL_RD) {
usb_cdc_loop();
if (cdc_rx_any()) {
ret |= MP_STREAM_POLL_RD;
}
}
if (poll_flags & MP_STREAM_POLL_WR) {
ret |= MP_STREAM_POLL_WR;
}
return ret;
}
int mp_hal_stdin_rx_chr(void) {
for (;;) {
usb_cdc_loop();
if (cdc_rx_any()) {
return cdc_rx_char();
}
MICROPY_EVENT_POLL_HOOK
}
return 0;
}
mp_uint_t 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);
usb_cdc_loop();
}
return len;
}
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');
usb_cdc_loop();
}
ringbuf_put((ringbuf_t*)&tx_ringbuf, *str);
usb_cdc_loop();
}
}
void USBD_IRQHandler(void) { void USBD_IRQHandler(void) {
tud_int_handler(0); tud_int_handler(0);
} }

117
ports/nrf/drivers/usb/usb_descriptors.c

@ -1,117 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Damien P. George
*
* 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 "tusb.h"
#ifndef MICROPY_HW_USB_VID
#define MICROPY_HW_USB_VID (0xf055)
#define MICROPY_HW_USB_PID (0x9802)
#endif
#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
#define USBD_MAX_POWER_MA (250)
#define USBD_ITF_CDC (0) // needs 2 interfaces
#define USBD_ITF_MAX (2)
#define USBD_CDC_EP_CMD (0x81)
#define USBD_CDC_EP_OUT (0x02)
#define USBD_CDC_EP_IN (0x82)
#define USBD_CDC_CMD_MAX_SIZE (8)
#define USBD_CDC_IN_OUT_MAX_SIZE (64)
#define USBD_STR_0 (0x00)
#define USBD_STR_MANUF (0x01)
#define USBD_STR_PRODUCT (0x02)
#define USBD_STR_SERIAL (0x03)
#define USBD_STR_CDC (0x04)
// Note: descriptors returned from callbacks must exist long enough for transfer to complete
static const tusb_desc_device_t usbd_desc_device = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
.bDeviceClass = TUSB_CLASS_MISC,
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
.bDeviceProtocol = MISC_PROTOCOL_IAD,
.bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE,
.idVendor = MICROPY_HW_USB_VID,
.idProduct = MICROPY_HW_USB_PID,
.bcdDevice = 0x0100,
.iManufacturer = USBD_STR_MANUF,
.iProduct = USBD_STR_PRODUCT,
.iSerialNumber = USBD_STR_SERIAL,
.bNumConfigurations = 1,
};
static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = {
TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN,
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA),
TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD,
USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE),
};
static const char *const usbd_desc_str[] = {
[USBD_STR_MANUF] = "MicroPython",
[USBD_STR_PRODUCT] = "Board in FS mode",
[USBD_STR_SERIAL] = "000000000000", // TODO
[USBD_STR_CDC] = "Board CDC",
};
const uint8_t *tud_descriptor_device_cb(void) {
return (const uint8_t*)&usbd_desc_device;
}
const uint8_t *tud_descriptor_configuration_cb(uint8_t index) {
(void)index;
return usbd_desc_cfg;
}
const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
#define DESC_STR_MAX (20)
static uint16_t desc_str[DESC_STR_MAX];
uint8_t len;
if (index == 0) {
desc_str[1] = 0x0409; // supported language is English
len = 1;
} else {
if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) {
return NULL;
}
const char* str = usbd_desc_str[index];
for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) {
desc_str[1 + len] = str[len];
}
}
// first byte is length (including header), second byte is string type
desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2 * len + 2);
return desc_str;
}

10
ports/nrf/main.c

@ -73,7 +73,7 @@
#include "softpwm.h" #include "softpwm.h"
#endif #endif
#if MICROPY_HW_USB_CDC #if MICROPY_HW_ENABLE_USBDEV && MICROPY_HW_USB_CDC
#include "usb_cdc.h" #include "usb_cdc.h"
#endif #endif
@ -165,11 +165,11 @@ soft_reset:
uart_init0(); uart_init0();
#endif #endif
#if (MICROPY_PY_BLE_NUS == 0) && (MICROPY_HW_USB_CDC == 0) #if MICROPY_HW_ENABLE_UART_REPL
{ {
mp_obj_t args[2] = { mp_obj_t args[2] = {
MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_NEW_SMALL_INT(MICROPY_HW_UART_REPL),
MP_OBJ_NEW_SMALL_INT(115200), MP_OBJ_NEW_SMALL_INT(MICROPY_HW_UART_REPL_BAUD),
}; };
MP_STATE_VM(dupterm_objs[0]) = MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, make_new)((mp_obj_t)&machine_uart_type, MP_ARRAY_SIZE(args), 0, args); MP_STATE_VM(dupterm_objs[0]) = MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, make_new)((mp_obj_t)&machine_uart_type, MP_ARRAY_SIZE(args), 0, args);
} }
@ -265,7 +265,7 @@ soft_reset:
ret_code = pyexec_file_if_exists("boot.py"); ret_code = pyexec_file_if_exists("boot.py");
#endif #endif
#if MICROPY_HW_USB_CDC #if MICROPY_HW_ENABLE_USBDEV && MICROPY_HW_USB_CDC
usb_cdc_init(); usb_cdc_init();
#endif #endif

39
ports/nrf/mpconfigport.h

@ -158,8 +158,7 @@
#define MICROPY_STREAMS_NON_BLOCK (1) #define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1) #define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_USE_INTERNAL_ERRNO (1)
#if MICROPY_HW_USB_CDC_1200BPS_TOUCH #if MICROPY_HW_ENABLE_USBDEV
#define MICROPY_HW_ENABLE_USBDEV (1)
#define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_ENABLE_SCHEDULER (1)
#define MICROPY_SCHEDULER_STATIC_NODES (1) #define MICROPY_SCHEDULER_STATIC_NODES (1)
#endif #endif
@ -297,6 +296,24 @@
#define MICROPY_PY_BLE_NUS (0) #define MICROPY_PY_BLE_NUS (0)
#endif #endif
// Whether to enable the REPL on a UART.
#ifndef MICROPY_HW_ENABLE_UART_REPL
// note: if both uart repl and cdc are enabled, uart hwfc can cause the cdc to lock up.
#define MICROPY_HW_ENABLE_UART_REPL (!MICROPY_PY_BLE_NUS && !MICROPY_HW_USB_CDC)
#endif
#if MICROPY_HW_ENABLE_UART_REPL
#ifndef MICROPY_HW_UART_REPL
#define MICROPY_HW_UART_REPL (0)
#endif
#ifndef MICROPY_HW_UART_REPL_BAUD
#define MICROPY_HW_UART_REPL_BAUD (115200)
#endif
#endif
// type definitions for the specific machine // type definitions for the specific machine
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1)) #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1))
@ -331,17 +348,21 @@ long unsigned int rng_generate_random_word(void);
#define MP_STATE_PORT MP_STATE_VM #define MP_STATE_PORT MP_STATE_VM
#if MICROPY_HW_USB_CDC #if MICROPY_HW_ENABLE_USBDEV
#include "device/usbd.h" #ifndef MICROPY_HW_USB_CDC
#define MICROPY_HW_USBDEV_TASK_HOOK extern void tud_task(void); tud_task(); #define MICROPY_HW_USB_CDC (1)
#define MICROPY_EXCLUDE_SHARED_TINYUSB_USBD_CDC (1) #endif
#else
#define MICROPY_HW_USBDEV_TASK_HOOK ; #ifndef MICROPY_HW_USB_VID
#define MICROPY_HW_USB_VID (0xf055)
#endif
#ifndef MICROPY_HW_USB_PID
#define MICROPY_HW_USB_PID (0x9802)
#endif #endif
#endif // MICROPY_HW_ENABLE_USBDEV
#define MICROPY_EVENT_POLL_HOOK \ #define MICROPY_EVENT_POLL_HOOK \
do { \ do { \
MICROPY_HW_USBDEV_TASK_HOOK \
extern void mp_handle_pending(bool); \ extern void mp_handle_pending(bool); \
mp_handle_pending(true); \ mp_handle_pending(true); \
__WFI(); \ __WFI(); \

86
ports/nrf/mphalport.c

@ -29,11 +29,15 @@
#include "py/mpstate.h" #include "py/mpstate.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "py/mperrno.h" #include "py/mperrno.h"
#include "py/ringbuf.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "py/stream.h" #include "py/stream.h"
#include "extmod/misc.h"
#include "uart.h" #include "uart.h"
#include "nrfx_errors.h" #include "nrfx_errors.h"
#include "nrfx_config.h" #include "nrfx_config.h"
#include "drivers/bluetooth/ble_uart.h"
#include "shared/tinyusb/mp_usbd_cdc.h"
#if MICROPY_PY_TIME_TICKS #if MICROPY_PY_TIME_TICKS
#include "nrfx_rtc.h" #include "nrfx_rtc.h"
@ -50,6 +54,14 @@
#include "soc/nrfx_coredep.h" #include "soc/nrfx_coredep.h"
#endif #endif
#ifndef MICROPY_HW_STDIN_BUFFER_LEN
#define MICROPY_HW_STDIN_BUFFER_LEN 512
#endif
static uint8_t stdin_ringbuf_array[MICROPY_HW_STDIN_BUFFER_LEN];
ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0 };
void mp_nrf_start_lfclk(void) { void mp_nrf_start_lfclk(void) {
if (!nrf_clock_lf_start_task_status_get(NRF_CLOCK)) { if (!nrf_clock_lf_start_task_status_get(NRF_CLOCK)) {
// Check if the clock was recently stopped but is still running. // Check if the clock was recently stopped but is still running.
@ -200,47 +212,73 @@ void mp_hal_set_interrupt_char(int c) {
} }
#endif #endif
#if !MICROPY_PY_BLE_NUS && !MICROPY_HW_USB_CDC
uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
uintptr_t ret = 0; uintptr_t ret = 0;
if ((poll_flags & MP_STREAM_POLL_RD) && MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL #if MICROPY_HW_ENABLE_USBDEV && MICROPY_HW_USB_CDC
&& uart_rx_any(MP_STATE_VM(dupterm_objs[0]))) { ret |= mp_usbd_cdc_poll_interfaces(poll_flags);
ret |= MP_STREAM_POLL_RD; #endif
} #if MICROPY_PY_BLE_NUS && MICROPY_PY_SYS_STDFILES
if ((poll_flags & MP_STREAM_POLL_WR) && MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL) { ret |= mp_ble_uart_stdio_poll(poll_flags);
ret |= MP_STREAM_POLL_WR; #endif
} #if MICROPY_PY_OS_DUPTERM
ret |= mp_os_dupterm_poll(poll_flags);
#endif
return ret; return ret;
} }
int mp_hal_stdin_rx_chr(void) { int mp_hal_stdin_rx_chr(void) {
for (;;) { for (;;) {
if (MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL && uart_rx_any(MP_STATE_VM(dupterm_objs[0]))) { #if MICROPY_HW_ENABLE_USBDEV && MICROPY_HW_USB_CDC
return uart_rx_char(MP_STATE_VM(dupterm_objs[0])); mp_usbd_cdc_poll_interfaces(0);
#endif
int c = ringbuf_get(&stdin_ringbuf);
if (c != -1) {
return c;
}
#if MICROPY_PY_BLE_NUS
c = mp_ble_uart_stdin_rx_chr();
if (c != -1) {
return c;
}
#endif
#if MICROPY_PY_OS_DUPTERM
int dupterm_c = mp_os_dupterm_rx_chr();
if (dupterm_c >= 0) {
return dupterm_c;
} }
#endif
MICROPY_EVENT_POLL_HOOK MICROPY_EVENT_POLL_HOOK
} }
return 0; return 0;
} }
// Send string of given length
mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
if (MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL) { mp_uint_t ret = len;
uart_tx_strn(MP_STATE_VM(dupterm_objs[0]), str, len); bool did_write = false;
return len; #if MICROPY_HW_ENABLE_USBDEV && MICROPY_HW_USB_CDC
mp_uint_t cdc_res = mp_usbd_cdc_tx_strn(str, len);
if (cdc_res > 0) {
did_write = true;
ret = MIN(cdc_res, ret);
} }
return 0; #endif
} #if MICROPY_PY_BLE_NUS
mp_uint_t ble_res = mp_ble_uart_stdout_tx_strn(str, len);
void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { if (ble_res > 0) {
if (MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL) { did_write = true;
uart_tx_strn_cooked(MP_STATE_VM(dupterm_objs[0]), str, len); ret = MIN(ble_res, ret);
} }
} #endif
#endif #if MICROPY_PY_OS_DUPTERM
int dupterm_res = mp_os_dupterm_tx_strn(str, len);
void mp_hal_stdout_tx_str(const char *str) { if (dupterm_res >= 0) {
mp_hal_stdout_tx_strn(str, strlen(str)); did_write = true;
ret = MIN((mp_uint_t)dupterm_res, ret);
}
#endif
return did_write ? ret : 0;
} }
#if MICROPY_PY_TIME_TICKS #if MICROPY_PY_TIME_TICKS

4
ports/nrf/mphalport.h

@ -28,10 +28,12 @@
#define __NRF52_HAL #define __NRF52_HAL
#include "py/mpconfig.h" #include "py/mpconfig.h"
#include "py/ringbuf.h"
#include <nrfx.h> #include <nrfx.h>
#include "pin.h" #include "pin.h"
#include "nrf_gpio.h" #include "nrf_gpio.h"
#include "nrfx_config.h" #include "nrfx_config.h"
#include "shared/runtime/interrupt_char.h"
typedef enum typedef enum
{ {
@ -43,6 +45,8 @@ typedef enum
extern const unsigned char mp_hal_status_to_errno_table[4]; extern const unsigned char mp_hal_status_to_errno_table[4];
extern ringbuf_t stdin_ringbuf;
NORETURN void mp_hal_raise(HAL_StatusTypeDef status); NORETURN void mp_hal_raise(HAL_StatusTypeDef status);
void mp_hal_set_interrupt_char(int c); // -1 to disable void mp_hal_set_interrupt_char(int c); // -1 to disable

Loading…
Cancel
Save