From 0747c4b61bdb19f2c2e7ecf4ce7033d69487bb76 Mon Sep 17 00:00:00 2001 From: Kamil Tomaszewski Date: Thu, 3 Oct 2019 14:22:43 +0200 Subject: [PATCH 1/6] Add Spresense board --- .gitmodules | 3 + examples/make.mk | 4 + examples/rules.mk | 6 +- hw/bsp/spresense/board.mk | 47 ++++ hw/bsp/spresense/board_spresense.c | 105 ++++++++ hw/mcu/sony/cxd56/spresense-exported-sdk | 1 + src/portable/sony/cxd56/dcd_cxd56.c | 321 +++++++++++++++++++++++ src/tusb_option.h | 2 + 8 files changed, 488 insertions(+), 1 deletion(-) create mode 100644 hw/bsp/spresense/board.mk create mode 100644 hw/bsp/spresense/board_spresense.c create mode 160000 hw/mcu/sony/cxd56/spresense-exported-sdk create mode 100644 src/portable/sony/cxd56/dcd_cxd56.c diff --git a/.gitmodules b/.gitmodules index f61ef719c..ad85278bf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "hw/mcu/st/st_driver"] path = hw/mcu/st/st_driver url = https://github.com/hathach/st_driver.git +[submodule "hw/mcu/sony/cxd56/spresense-exported-sdk"] + path = hw/mcu/sony/cxd56/spresense-exported-sdk + url = https://github.com/sonydevworld/spresense-exported-sdk.git diff --git a/examples/make.mk b/examples/make.mk index 22d8f7455..699cc43d6 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -80,5 +80,9 @@ CFLAGS += \ ifeq ($(DEBUG), 1) CFLAGS += -O0 -ggdb -DCFG_TUSB_DEBUG=1 else +ifneq ($(BOARD), spresense) CFLAGS += -flto -Os +else + CFLAGS += -Os +endif endif diff --git a/examples/rules.mk b/examples/rules.mk index c3daf9dac..c6997c040 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -3,7 +3,11 @@ # # libc -LIBS += -lgcc -lc -lm -lnosys +LIBS += -lgcc -lm -lnosys + +ifneq ($(BOARD), spresense) +LIBS += -lc +endif # TinyUSB Stack source SRC_C += \ diff --git a/hw/bsp/spresense/board.mk b/hw/bsp/spresense/board.mk new file mode 100644 index 000000000..16421686a --- /dev/null +++ b/hw/bsp/spresense/board.mk @@ -0,0 +1,47 @@ +SPRESENSE_SDK = $(TOP)/hw/mcu/sony/cxd56/spresense-exported-sdk + +INC += \ + $(SPRESENSE_SDK)/nuttx/include \ + $(SPRESENSE_SDK)/nuttx/arch \ + $(SPRESENSE_SDK)/nuttx/arch/chip \ + $(SPRESENSE_SDK)/sdk/bsp/include \ + $(SPRESENSE_SDK)/sdk/bsp/include/sdk \ + +CFLAGS += \ + -DCONFIG_WCHAR_BUILTIN \ + -DCONFIG_HAVE_DOUBLE \ + -Dmain=spresense_main \ + -pipe \ + -std=gnu11 \ + -mcpu=cortex-m4 \ + -mthumb \ + -mfpu=fpv4-sp-d16 \ + -mfloat-abi=hard \ + -mabi=aapcs \ + -fno-builtin \ + -fno-strength-reduce \ + -fomit-frame-pointer \ + -DCFG_TUSB_MCU=OPT_MCU_CXD56 \ + +LIBS += \ + $(SPRESENSE_SDK)/sdk/libs/libapps.a \ + $(SPRESENSE_SDK)/sdk/libs/libsdk.a \ + +LD_FILE = hw/mcu/sony/cxd56/spresense-exported-sdk/nuttx/build/ramconfig.ld + +LDFLAGS += \ + -Xlinker --entry=__start \ + -nostartfiles \ + -nodefaultlibs \ + -Wl,--defsym,__stack=_vectors+786432 \ + -Wl,--gc-sections \ + -u spresense_main \ + +# For TinyUSB port source +VENDOR = sony +CHIP_FAMILY = cxd56 + +# flash +flash: + $(SPRESENSE_SDK)/sdk/tools/linux/mkspk -c 2 $(BUILD)/spresense-firmware.elf nuttx $(BUILD)/spresense-firmware.spk + $(SPRESENSE_SDK)/sdk/tools/flash.sh -c /dev/ttyUSB0 $(BUILD)/spresense-firmware.spk diff --git a/hw/bsp/spresense/board_spresense.c b/hw/bsp/spresense/board_spresense.c new file mode 100644 index 000000000..256bccd15 --- /dev/null +++ b/hw/bsp/spresense/board_spresense.c @@ -0,0 +1,105 @@ +/* + * The MIT License (MIT) + * + * Copyright 2019 Sony Semiconductor Solutions Corporation + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include +#include +#include +#include + +#include "bsp/board.h" + +/*------------------------------------------------------------------*/ +/* MACRO TYPEDEF CONSTANT ENUM + *------------------------------------------------------------------*/ +#define LED_PIN PIN_I2S1_BCK + +#define BUTTON_PIN PIN_HIF_IRQ_OUT + +// Initialize on-board peripherals : led, button, uart and USB +void board_init(void) +{ + boardctl(BOARDIOC_INIT, 0); + + board_gpio_write(PIN_I2S1_BCK, -1); + board_gpio_config(PIN_I2S1_BCK, 0, false, true, PIN_FLOAT); + + board_gpio_write(PIN_HIF_IRQ_OUT, -1); + board_gpio_config(PIN_HIF_IRQ_OUT, 0, true, true, PIN_FLOAT); +}; + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +// Turn LED on or off +void board_led_write(bool state) +{ + board_gpio_write(LED_PIN, state); +} + +// Get the current state of button +// a '1' means active (pressed), a '0' means inactive. +uint32_t board_button_read(void) +{ + if (board_gpio_read(BUTTON_PIN)) + { + return 0; + } + + return 1; +} + +// Get characters from UART +int board_uart_read(uint8_t *buf, int len) +{ + int r = read(0, buf, len); + + return r; +} + +// Send characters to UART +int board_uart_write(void const *buf, int len) +{ + int r = write(1, buf, len); + + return r; +} + +// Get current milliseconds +uint32_t board_millis(void) +{ + struct timespec tp; + + /* Wait until RTC is available */ + while (g_rtc_enabled == false); + + if (clock_gettime(CLOCK_MONOTONIC, &tp)) + { + return 0; + } + + return (((uint64_t)tp.tv_sec) * 1000 + tp.tv_nsec / 1000000); +} diff --git a/hw/mcu/sony/cxd56/spresense-exported-sdk b/hw/mcu/sony/cxd56/spresense-exported-sdk new file mode 160000 index 000000000..b473b28a1 --- /dev/null +++ b/hw/mcu/sony/cxd56/spresense-exported-sdk @@ -0,0 +1 @@ +Subproject commit b473b28a14a03f3d416b6e2c071bcfd4fb92cb63 diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c new file mode 100644 index 000000000..32eb50a6f --- /dev/null +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -0,0 +1,321 @@ +/* + * The MIT License (MIT) + * + * Copyright 2019 Sony Semiconductor Solutions Corporation + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_CXD56 + +#include +#include + +#include "device/dcd.h" + +#define CXD56_EPNUM (7) + +struct usbdcd_driver_s +{ + struct usbdevclass_driver_s usbdevclass_driver; + FAR struct usbdev_ep_s *ep[CXD56_EPNUM]; + FAR struct usbdev_req_s *req[CXD56_EPNUM]; +}; + +static struct usbdcd_driver_s usbdcd_driver; +static struct usbdev_s *usbdev; + +static int dcd_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); +static void dcd_unbind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); +static int dcd_setup(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen); +static void dcd_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); +static void dcd_suspend(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); +static void dcd_resume(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev); + +static const struct usbdevclass_driverops_s g_driverops = +{ + dcd_bind, /* bind */ + dcd_unbind, /* unbind */ + dcd_setup, /* setup */ + dcd_disconnect, /* disconnect */ + dcd_suspend, /* suspend */ + dcd_resume, /* resume */ +}; + +static void usbdcd_ep0incomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req) +{ + (void) ep; + + uint8_t ep_addr = (uint32_t)req->priv; + + if (req->result || req->xfrd != req->len) + { + if (req->len) + { + dcd_event_xfer_complete(0, ep_addr, req->xfrd, XFER_RESULT_SUCCESS, true); + } + } + else + { + if (req->xfrd) + { + dcd_event_xfer_complete(0, ep_addr, req->xfrd, XFER_RESULT_SUCCESS, true); + } + } +} + +static int dcd_bind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) +{ + (void) driver; + + usbdev = dev; + usbdcd_driver.ep[0] = dev->ep0; + + usbdcd_driver.req[0] = EP_ALLOCREQ(usbdcd_driver.ep[0]); + if (usbdcd_driver.req[0] != NULL) + { + usbdcd_driver.req[0]->len = 64; + usbdcd_driver.req[0]->buf = EP_ALLOCBUFFER(usbdcd_driver.ep[0], 64); + if (!usbdcd_driver.req[0]->buf) + { + EP_FREEREQ(usbdcd_driver.ep[0], usbdcd_driver.req[0]); + usbdcd_driver.req[0] = NULL; + } + } + + usbdcd_driver.req[0]->callback = usbdcd_ep0incomplete; + + DEV_CONNECT(dev); + return 0; +} + +static void dcd_unbind(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) +{ + (void) driver; + (void) dev; +} + +static int dcd_setup(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev, + FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout, size_t outlen) +{ + (void) driver; + (void) dev; + (void) dataout; + (void) outlen; + + dcd_event_setup_received(0, (uint8_t *)ctrl, true); + + return 0; +} + +static void dcd_disconnect(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) +{ + (void) driver; + + dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); + DEV_CONNECT(dev); +} + +static void dcd_suspend(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) +{ + (void) driver; + (void) dev; +} + +static void dcd_resume(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) +{ + (void) driver; + (void) dev; +} + +void dcd_init(uint8_t rhport) +{ + (void) rhport; + + usbdcd_driver.usbdevclass_driver.speed = USB_SPEED_HIGH; + usbdcd_driver.usbdevclass_driver.ops = &g_driverops; + + usbdev_register(&usbdcd_driver.usbdevclass_driver); +} + +// Enable device interrupt +void dcd_int_enable(uint8_t rhport) +{ + (void) rhport; +} + +// Disable device interrupt +void dcd_int_disable(uint8_t rhport) +{ + (void) rhport; +} + +// Receive Set Address request, mcu port must also include status IN response +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void) rhport; + (void) dev_addr; +} + +// Receive Set Config request +void dcd_set_config(uint8_t rhport, uint8_t config_num) +{ + (void) rhport; + (void) config_num; +} + +void dcd_remote_wakeup(uint8_t rhport) +{ + (void) rhport; + + DEV_WAKEUP(usbdev); +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) +{ + (void) rhport; + + uint8_t epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); + uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + uint8_t xfrtype = 0; + struct usb_epdesc_s epdesc; + + if (epnum >= CXD56_EPNUM) + { + return false; + } + + switch (p_endpoint_desc->bmAttributes.xfer) + { + case 1: + xfrtype = USB_EP_ATTR_XFER_ISOC; + break; + case 2: + xfrtype = USB_EP_ATTR_XFER_BULK; + break; + case 3: + xfrtype = USB_EP_ATTR_XFER_INT; + break; + } + + usbdcd_driver.ep[epnum] = DEV_ALLOCEP(usbdev, epnum, dir == TUSB_DIR_IN, xfrtype); + if (usbdcd_driver.ep[epnum] == NULL) + { + return false; + } + + usbdcd_driver.req[epnum] = NULL; + usbdcd_driver.req[epnum] = EP_ALLOCREQ(usbdcd_driver.ep[epnum]); + if (usbdcd_driver.req[epnum] != NULL) + { + usbdcd_driver.req[epnum]->len = p_endpoint_desc->wMaxPacketSize.size; + } + else + { + return false; + } + + usbdcd_driver.req[epnum]->callback = usbdcd_ep0incomplete; + + epdesc.len = p_endpoint_desc->bLength; + epdesc.type = p_endpoint_desc->bDescriptorType; + epdesc.addr = p_endpoint_desc->bEndpointAddress; + epdesc.attr = xfrtype; + epdesc.mxpacketsize[0] = LSBYTE(p_endpoint_desc->wMaxPacketSize.size); + epdesc.mxpacketsize[1] = MSBYTE(p_endpoint_desc->wMaxPacketSize.size); + epdesc.interval = p_endpoint_desc->bInterval; + + if (EP_CONFIGURE(usbdcd_driver.ep[epnum], &epdesc, false) < 0) + { + return false; + } + + return true; +} + +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + (void) rhport; + + uint8_t epnum = tu_edpt_number(ep_addr); + + if (epnum >= CXD56_EPNUM) + { + return false; + } + + usbdcd_driver.req[epnum]->len = total_bytes; + usbdcd_driver.req[epnum]->priv = (void *)((uint32_t)ep_addr); + usbdcd_driver.req[epnum]->flags = 0; + + if (total_bytes) + { + usbdcd_driver.req[epnum]->buf = buffer; + } + else + { + return true; + } + + if (EP_SUBMIT(usbdcd_driver.ep[epnum], usbdcd_driver.req[epnum]) < 0) + { + return false; + } + + return true; +} + +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t epnum = tu_edpt_number(ep_addr); + + if (epnum >= CXD56_EPNUM) + { + return; + } + + EP_STALL(usbdcd_driver.ep[epnum]); +} + +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t epnum = tu_edpt_number(ep_addr); + + if (epnum >= CXD56_EPNUM) + { + return; + } + + EP_RESUME(usbdcd_driver.ep[epnum]); +} + +#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 76ea59758..28664c732 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -67,6 +67,8 @@ #define OPT_MCU_STM32L1 308 ///< ST STM32L1 #define OPT_MCU_STM32L4 309 ///< ST STM32L4 +#define OPT_MCU_CXD56 400 ///< SONY CXD56 + /** @} */ /** \defgroup group_supported_os Supported RTOS From b3872febe2651d51a08941352dc1a5e66df74d4b Mon Sep 17 00:00:00 2001 From: Kamil Tomaszewski Date: Mon, 7 Oct 2019 14:03:02 +0200 Subject: [PATCH 2/6] Disable/enable interrupt --- src/portable/sony/cxd56/dcd_cxd56.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 32eb50a6f..3698e5103 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -163,12 +163,16 @@ void dcd_init(uint8_t rhport) void dcd_int_enable(uint8_t rhport) { (void) rhport; + + __asm volatile ("cpsie i" : : : "memory"); } // Disable device interrupt void dcd_int_disable(uint8_t rhport) { (void) rhport; + + __asm volatile ("cpsid i" : : : "memory"); } // Receive Set Address request, mcu port must also include status IN response From 992360422113d15266552c5e488d87e0db60345e Mon Sep 17 00:00:00 2001 From: Kamil Tomaszewski Date: Mon, 7 Oct 2019 14:04:48 +0200 Subject: [PATCH 3/6] Send SUSPEND and RESUME signals --- src/portable/sony/cxd56/dcd_cxd56.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 3698e5103..38f3b5c75 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -141,12 +141,16 @@ static void dcd_suspend(FAR struct usbdevclass_driver_s *driver, FAR struct usbd { (void) driver; (void) dev; + + dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } static void dcd_resume(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev) { (void) driver; (void) dev; + + dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } void dcd_init(uint8_t rhport) From 0cea82568c318f1fb0cc2ade0e23811c4a13e724 Mon Sep 17 00:00:00 2001 From: Kamil Tomaszewski Date: Tue, 8 Oct 2019 09:58:56 +0200 Subject: [PATCH 4/6] Disable/enable only USB interrupt --- src/portable/sony/cxd56/dcd_cxd56.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 38f3b5c75..638b2f979 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -30,6 +30,7 @@ #include #include +#include #include "device/dcd.h" @@ -168,7 +169,7 @@ void dcd_int_enable(uint8_t rhport) { (void) rhport; - __asm volatile ("cpsie i" : : : "memory"); + up_enable_irq(CXD56_IRQ_USB_INT); } // Disable device interrupt @@ -176,7 +177,7 @@ void dcd_int_disable(uint8_t rhport) { (void) rhport; - __asm volatile ("cpsid i" : : : "memory"); + up_disable_irq(CXD56_IRQ_USB_INT); } // Receive Set Address request, mcu port must also include status IN response From 0b6c031948458da2ebb510e9e12c418b88325d59 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 8 Oct 2019 15:49:37 +0700 Subject: [PATCH 5/6] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b82a88955..f2c8805b3 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ The stack supports the following MCUs - **Nordic:** nRF52840 - **NXP:** LPC Series: 11Uxx, 13xx, 175x_6x, 177x_8x, 18xx, 40xx, 43xx, 51Uxx - **MicroChip:** SAMD21, SAMD51 (device only) +- **Sony:** CXD56 - **ST:** STM32 series: L0, F0, F1, F2, F3, F4, F7, H7 (device only) [Here is the list of supported Boards](docs/boards.md) that can be used with provided examples. From b3a5bb3247dfac081a01ccb22498ee2f50e365b4 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 8 Oct 2019 15:52:00 +0700 Subject: [PATCH 6/6] Update boards.md --- docs/boards.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/boards.md b/docs/boards.md index 0b38cf568..892236eca 100644 --- a/docs/boards.md +++ b/docs/boards.md @@ -39,6 +39,10 @@ This code base already had supported for a handful of following boards - [LPCXpresso 54114](https://www.nxp.com/design/microcontrollers-developer-resources/lpcxpresso-boards/lpcxpresso54114-board:OM13089) - [LPCXpresso 55s69 EVK](https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/lpc5500-cortex-m33/lpcxpresso55s69-development-board:LPC55S69-EVK) +### Sony + +- [Sony Spresense CXD5602](https://developer.sony.com/develop/spresense) + ### ST STM32 - Adafruit Feather STM32F405