Merge pull request #88 from adafruit/develop

adding support for nrf52833
This commit is contained in:
Ha Thach 2019-12-17 12:08:35 +07:00 committed by GitHub
commit a78d555f79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 478 additions and 491 deletions

View File

@ -21,7 +21,7 @@ SD_FILENAME = $(SD_NAME)_nrf52_$(SD_VERSION)
SD_API_PATH = $(SD_PATH)/$(SD_FILENAME)_API
SD_HEX = $(SD_PATH)/$(SD_FILENAME)_softdevice.hex
LD_FILE = $(SRC_PATH)/linker/$(SD_NAME)_v$(word 1, $(subst ., ,$(SD_VERSION))).ld
LD_FILE = $(SRC_PATH)/linker/$(MCU_SUB_VARIANT)_$(SD_NAME)_v$(word 1, $(subst ., ,$(SD_VERSION))).ld
MERGED_FNAME = $(OUTPUT_FILENAME)_$(SD_NAME)_$(SD_VERSION)
@ -76,23 +76,33 @@ remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-ou
#*********************************
BOARD_LIST = $(sort $(subst .h,,$(subst src/boards/,,$(wildcard src/boards/*))))
NRF52832_BOARDLIST = feather_nrf52832
IS_52832 = $(filter $(BOARD),$(NRF52832_BOARDLIST))
ifeq ($(filter $(BOARD),$(BOARD_LIST)),)
$(info You must provide a BOARD parameter with 'BOARD='. Supported boards are:)
$(info $(BOARD_LIST))
$(error Invalid BOARD specified)
endif
# Build directory
BUILD = _build-$(BOARD)
ifneq ($(IS_52832),)
SD_NAME = s132
DFU_DEV_REV = 0xADAF
# Board specific
-include src/boards/$(BOARD)/board.mk
# MCU_SUB_VARIANT can be nrf52 (nrf52832), nrf52833, nrf52840
ifeq ($(MCU_SUB_VARIANT),nrf52)
SD_NAME = s132
DFU_DEV_REV = 0xADAF
MCU_FLAGS = -DNRF52 -DNRF52832_XXAA -DS132
else ifeq ($(MCU_SUB_VARIANT),nrf52833)
SD_NAME = s140
DFU_DEV_REV = 52840
MCU_FLAGS = -DNRF52833_XXAA -DS140
else ifeq ($(MCU_SUB_VARIANT),nrf52840)
SD_NAME = s140
DFU_DEV_REV = 52840
MCU_FLAGS = -DNRF52840_XXAA -DS140
else
SD_NAME = s140
DFU_DEV_REV = 52840
$(error Sub Variant $(MCU_SUB_VARIANT) is unknown)
endif
#******************************************************************************
@ -108,7 +118,8 @@ C_SOURCE_FILES += $(SRC_PATH)/dfu_init.c
# nrfx
C_SOURCE_FILES += $(NRFX_PATH)/drivers/src/nrfx_power.c
C_SOURCE_FILES += $(NRFX_PATH)/hal/nrf_nvmc.c
C_SOURCE_FILES += $(NRFX_PATH)/drivers/src/nrfx_nvmc.c
C_SOURCE_FILES += $(NRFX_PATH)/mdk/system_$(MCU_SUB_VARIANT).c
# SDK 11 files
C_SOURCE_FILES += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader.c
@ -134,10 +145,8 @@ C_SOURCE_FILES += $(SDK_PATH)/libraries/hci/hci_slip.c
C_SOURCE_FILES += $(SDK_PATH)/libraries/hci/hci_transport.c
C_SOURCE_FILES += $(SDK_PATH)/libraries/util/nrf_assert.c
ifneq ($(IS_52832),)
C_SOURCE_FILES += $(NRFX_PATH)/mdk/system_nrf52.c
# UART or USB Serial
ifeq ($(MCU_SUB_VARIANT),nrf52)
C_SOURCE_FILES += $(SDK_PATH)/libraries/uart/app_uart.c
C_SOURCE_FILES += $(SDK_PATH)/drivers_nrf/uart/nrf_drv_uart.c
C_SOURCE_FILES += $(SDK_PATH)/drivers_nrf/common/nrf_drv_common.c
@ -147,25 +156,19 @@ IPATH += $(SDK_PATH)/drivers_nrf/common
IPATH += $(SDK_PATH)/drivers_nrf/uart
else
# src
C_SOURCE_FILES += $(SRC_PATH)/usb/usb_desc.c
C_SOURCE_FILES += $(SRC_PATH)/usb/usb.c
C_SOURCE_FILES += $(SRC_PATH)/usb/msc_uf2.c
C_SOURCE_FILES += $(SRC_PATH)/usb/uf2/ghostfat.c
# nrfx
C_SOURCE_FILES += $(NRFX_PATH)/mdk/system_nrf52840.c
# Tinyusb stack
# TinyUSB stack
C_SOURCE_FILES += $(TUSB_PATH)/portable/nordic/nrf5x/dcd_nrf5x.c
C_SOURCE_FILES += $(TUSB_PATH)/portable/nordic/nrf5x/hal_nrf5x.c
C_SOURCE_FILES += $(TUSB_PATH)/common/tusb_fifo.c
C_SOURCE_FILES += $(TUSB_PATH)/device/usbd.c
C_SOURCE_FILES += $(TUSB_PATH)/device/usbd_control.c
C_SOURCE_FILES += $(TUSB_PATH)/class/cdc/cdc_device.c
C_SOURCE_FILES += $(TUSB_PATH)/class/msc/msc_device.c
C_SOURCE_FILES += $(TUSB_PATH)/class/custom/custom_device.c
C_SOURCE_FILES += $(TUSB_PATH)/tusb.c
endif
@ -174,11 +177,7 @@ endif
#******************************************************************************
# Assembly Files
#******************************************************************************
ifneq ($(IS_52832),)
ASM_SOURCE_FILES = $(NRFX_PATH)/mdk/gcc_startup_nrf52.S
else
ASM_SOURCE_FILES = $(NRFX_PATH)/mdk/gcc_startup_nrf52840.S
endif
ASM_SOURCE_FILES = $(NRFX_PATH)/mdk/gcc_startup_$(MCU_SUB_VARIANT).S
#******************************************************************************
# INCLUDE PATH
@ -198,6 +197,7 @@ IPATH += $(NRFX_PATH)
IPATH += $(NRFX_PATH)/mdk
IPATH += $(NRFX_PATH)/hal
IPATH += $(NRFX_PATH)/drivers/include
IPATH += $(NRFX_PATH)/drivers/src
IPATH += $(SDK11_PATH)/libraries/bootloader_dfu/hci_transport
IPATH += $(SDK11_PATH)/libraries/bootloader_dfu
@ -245,6 +245,7 @@ CFLAGS += -DSWI_DISABLE0
CFLAGS += -DSOFTDEVICE_PRESENT
CFLAGS += -DFLOAT_ABI_HARD
CFLAGS += -DDFU_APP_DATA_RESERVED=7*4096
CFLAGS += $(MCU_FLAGS)
CFLAGS += -DUF2_VERSION='"$(GIT_VERSION) $(GIT_SUBMODULE_VERSIONS) $(SD_NAME) $(SD_VERSION)"'
CFLAGS += -DBLEDIS_FW_VERSION='"$(GIT_VERSION) $(SD_NAME) $(SD_VERSION)"'
@ -252,15 +253,6 @@ CFLAGS += -DBLEDIS_FW_VERSION='"$(GIT_VERSION) $(SD_NAME) $(SD_VERSION)"'
_VER = $(subst ., ,$(word 1, $(subst -, ,$(GIT_VERSION))))
CFLAGS += -DMK_BOOTLOADER_VERSION='($(word 1,$(_VER)) << 16) + ($(word 2,$(_VER)) << 8) + $(word 3,$(_VER))'
ifneq ($(IS_52832),)
CFLAGS += -DNRF52
CFLAGS += -DNRF52832_XXAA
CFLAGS += -DS132
else
CFLAGS += -DNRF52840_XXAA
CFLAGS += -DS140
endif
#******************************************************************************
# Linker Flags
@ -289,14 +281,7 @@ ASMFLAGS += -DBLE_STACK_SUPPORT_REQD
ASMFLAGS += -DSWI_DISABLE0
ASMFLAGS += -DSOFTDEVICE_PRESENT
ASMFLAGS += -DFLOAT_ABI_HARD
ifneq ($(IS_52832),)
ASMFLAGS += -DNRF52
ASMFLAGS += -DS132
else
ASMFLAGS += -DNRF52840_XXAA
ASMFLAGS += -DS140
endif
ASMFLAGS += $(MCU_FLAGS)
C_SOURCE_FILE_NAMES = $(notdir $(C_SOURCE_FILES))
C_PATHS = $(call remduplicates, $(dir $(C_SOURCE_FILES) ) )

View File

@ -109,7 +109,7 @@ You must have have a J-Link available to "unbrick" your device.
Prerequisites
- ARM GCC
- Nordic's [nRF5x Command Line Tools](http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.tools%2Fdita%2Ftools%2Fnrf5x_command_line_tools%2Fnrf5x_installation.html)
- Nordic's [nRF5x Command Line Tools](https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Command-Line-Tools)
To build:

@ -1 +1 @@
Subproject commit 096e770ee41e5ad92a2137aa6502cb04d5745e5c
Subproject commit 7a4c9d946cf1801771fc180acdbf7b878f270093

View File

@ -119,11 +119,23 @@ __STATIC_INLINE void apply_config(nrf_drv_uart_t const * p_instance, nrf_drv_uar
nrf_gpio_cfg_input(p_config->pselrxd, NRF_GPIO_PIN_NOPULL);
}
nrf_uarte_config_t uarte_cfg =
{
.hwfc = (nrf_uarte_hwfc_t) p_config->hwfc,
.parity = (nrf_uarte_parity_t) p_config->parity
};
nrf_uart_config_t uart_cfg =
{
.hwfc = (nrf_uart_hwfc_t) p_config->hwfc,
.parity = (nrf_uart_parity_t) p_config->parity
};
CODE_FOR_UARTE
(
nrf_uarte_baudrate_set(p_instance->reg.p_uarte, (nrf_uarte_baudrate_t)p_config->baudrate);
nrf_uarte_configure(p_instance->reg.p_uarte, (nrf_uarte_parity_t)p_config->parity,
(nrf_uarte_hwfc_t)p_config->hwfc);
// nrf_uarte_configure(p_instance->reg.p_uarte, (nrf_uarte_parity_t)p_config->parity, (nrf_uarte_hwfc_t)p_config->hwfc);
nrf_uarte_configure(p_instance->reg.p_uarte, &uarte_cfg);
nrf_uarte_txrx_pins_set(p_instance->reg.p_uarte, p_config->pseltxd, p_config->pselrxd);
if (p_config->hwfc == NRF_UART_HWFC_ENABLED)
{
@ -142,7 +154,8 @@ __STATIC_INLINE void apply_config(nrf_drv_uart_t const * p_instance, nrf_drv_uar
CODE_FOR_UART
(
nrf_uart_baudrate_set(p_instance->reg.p_uart, p_config->baudrate);
nrf_uart_configure(p_instance->reg.p_uart, p_config->parity, p_config->hwfc);
// nrf_uart_configure(p_instance->reg.p_uart, p_config->parity, p_config->hwfc);
nrf_uart_configure(p_instance->reg.p_uart, &uart_cfg);
nrf_uart_txrx_pins_set(p_instance->reg.p_uart, p_config->pseltxd, p_config->pselrxd);
if (p_config->hwfc == NRF_UART_HWFC_ENABLED)
{

View File

@ -44,7 +44,8 @@
#include "app_uart.h"
#include "nrf_error.h"
#ifdef NRF52840_XXAA
// nRF has native usb peripheral
#ifdef NRF_USBD
#include "tusb.h"
#endif
@ -121,13 +122,17 @@ static uint32_t send_tx_byte_end(void);
*/
uint32_t (*send_tx_byte) (void) = send_tx_byte_default;
#ifdef NRF52840_XXAA
static uint32_t serial_put(char ch)
{
return tud_cdc_write_char(ch) ? NRF_SUCCESS : NRF_ERROR_NO_MEM;
}
#ifdef NRF_USBD
static uint32_t serial_put(char ch)
{
return tud_cdc_write_char(ch) ? NRF_SUCCESS : NRF_ERROR_NO_MEM;
}
#else
#define serial_put app_uart_put
#define serial_put app_uart_put
#endif
static uint32_t send_tx_byte_end(void)
@ -345,7 +350,7 @@ static bool rx_buffer_overflowed(void)
return false;
}
#ifdef NRF52840_XXAA
#ifdef NRF_USBD
static uint32_t slip_uart_open(void)
{
@ -441,7 +446,8 @@ uint32_t hci_slip_open()
uint32_t hci_slip_close()
{
m_current_state = SLIP_OFF;
#ifdef NRF52840_XXAA
#ifdef NRF_USBD
return NRF_SUCCESS;
#else
uint32_t err_code = app_uart_close();

View File

@ -40,11 +40,11 @@
#define INVALID_OPCODE 0x00 /**< Invalid op code identifier. */
#ifdef NRF51
#define SOC_MAX_WRITE_SIZE 1024 /**< Maximum write size allowed for a single call to \ref sd_flash_write as specified in the SoC API on the nRF51. */
#elif defined(NRF52832_XXAA) || defined(NRF52840_XXAA)
#define SOC_MAX_WRITE_SIZE 4096 /**< Maximum write size allowed for a single call to \ref sd_flash_write as specified in the SoC API on the nRF52. */
#define SOC_MAX_WRITE_SIZE 1024 /**< Maximum write size allowed for a single call to \ref sd_flash_write as specified in the SoC API on the nRF51. */
#elif defined(NRF52_SERIES)
#define SOC_MAX_WRITE_SIZE 4096 /**< Maximum write size allowed for a single call to \ref sd_flash_write as specified in the SoC API on the nRF52. */
#else
#error No target defined
#error No target defined
#endif

View File

@ -32,7 +32,7 @@
#include "boards.h"
#ifdef NRF52840_XXAA
#ifdef NRF_USBD
#include "tusb.h"
#endif
@ -40,11 +40,11 @@
#define IRQ_ENABLED 0x01 /**< Field identifying if an interrupt is enabled. */
/**< Maximum number of interrupts available. */
/**< Maximum number of interrupts available. (from IRQn_Type) */
#if defined(NRF52832_XXAA)
#define MAX_NUMBER_INTERRUPTS 39
#elif defined(NRF52840_XXAA)
#define MAX_NUMBER_INTERRUPTS 48
#define MAX_NUMBER_INTERRUPTS 39
#elif defined(NRF52840_XXAA) || defined(NRF52833_XXAA)
#define MAX_NUMBER_INTERRUPTS 48
#endif
/**@brief Enumeration for specifying current bootloader status.
@ -119,17 +119,16 @@ static void wait_for_events(void)
// Feed all Watchdog just in case application enable it
// WDT cannot be disabled once started. It even last through soft reset (NVIC Reset)
if ( nrf_wdt_started() )
if ( nrf_wdt_started(NRF_WDT) )
{
for (uint8_t i=0; i<8; i++) nrf_wdt_reload_request_set(i);
for (uint8_t i=0; i<8; i++) nrf_wdt_reload_request_set(NRF_WDT, i);
}
// Event received. Process it from the scheduler.
app_sched_execute();
#ifdef NRF52840_XXAA
#ifdef NRF_USBD
// skip if usb is not inited ( e.g OTA / finializing sd/bootloader )
extern bool usb_inited(void);
if ( tusb_inited() )
{
tud_task();
@ -194,8 +193,8 @@ static void bootloader_settings_save(bootloader_settings_t * p_settings)
}
else
{
nrf_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS);
nrf_nvmc_write_words(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t *) p_settings, sizeof(bootloader_settings_t) / 4);
nrfx_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS);
nrfx_nvmc_words_write(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t *) p_settings, sizeof(bootloader_settings_t) / 4);
pstorage_callback_handler(&m_bootsettings_handle, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_settings, sizeof(bootloader_settings_t));
}

View File

@ -31,7 +31,7 @@ __root const uint32_t m_uicr_bootloader_start_address @ NRF_UICR_BOOT_START_A
#endif
#if defined(NRF52832_XXAA) || defined(NRF52840_XXAA)
#if defined(NRF52_SERIES)
#if defined ( __CC_ARM )
uint8_t m_mbr_params_page[CODE_PAGE_SIZE] __attribute__((at(BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS))) __attribute__((used)); /**< This variable reserves a codepage for mbr parameters, to ensure the compiler doesn't locate any code or variables at his location. */
@ -50,7 +50,7 @@ __no_init uint8_t m_mbr_params_page[CODE_PAGE_SIZE] @ BOOTLOADER_MBR_PARAMS_
__root const uint32_t m_uicr_mbr_params_page_address @ NRF_UICR_MBR_PARAMS_PAGE_ADDRESS = BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS; /**< This variable ensures that the linker script will write the bootloader start address to the UICR register. This value will be written in the HEX file and thus written to UICR when the bootloader is flashed into the chip. */
#endif
#endif // defined(NRF52832_XXAA) || defined(NRF52840_XXAA)
#endif // NRF52_SERIES
void bootloader_util_settings_get(const bootloader_settings_t ** pp_bootloader_settings)

View File

@ -151,7 +151,7 @@ static void dfu_prepare_func_app_erase(uint32_t image_size)
for ( uint32_t i = 0; i < page_count; i++ )
{
nrf_nvmc_page_erase(DFU_BANK_0_REGION_START + i * CODE_PAGE_SIZE);
nrfx_nvmc_page_erase(DFU_BANK_0_REGION_START + i * CODE_PAGE_SIZE);
}
// invoke complete callback

View File

@ -30,22 +30,20 @@
#include "app_util.h"
#define NRF_UICR_BOOT_START_ADDRESS (NRF_UICR_BASE + 0x14) /**< Register where the bootloader start address is stored in the UICR register. */
#if defined(NRF52832_XXAA) || defined(NRF52840_XXAA)
#define NRF_UICR_MBR_PARAMS_PAGE_ADDRESS (NRF_UICR_BASE + 0x18) /**< Register where the mbr params page is stored in the UICR register. (Only in use in nRF52 MBR).*/
#endif
#define CODE_REGION_1_START SD_SIZE_GET(MBR_SIZE) /**< This field should correspond to the size of Code Region 0, (which is identical to Start of Code Region 1), found in UICR.CLEN0 register. This value is used for compile safety, as the linker will fail if application expands into bootloader. Runtime, the bootloader will use the value found in UICR.CLEN0. */
#define SOFTDEVICE_REGION_START MBR_SIZE /**< This field should correspond to start address of the bootloader, found in UICR.RESERVED, 0x10001014, register. This value is used for sanity check, so the bootloader will fail immediately if this value differs from runtime value. The value is used to determine max application size for updating. */
#define CODE_PAGE_SIZE 0x1000 /**< Size of a flash codepage. Used for size of the reserved flash space in the bootloader region. Will be runtime checked against NRF_UICR->CODEPAGESIZE to ensure the region is correct. */
#if defined(NRF52832_XXAA)
// Flash = 512 KB
#if defined(NRF52832_XXAA) || defined(NRF52833_XXAA)
#define BOOTLOADER_REGION_START 0x00074000 /**< This field should correspond to start address of the bootloader, found in UICR.RESERVED, 0x10001014, register. This value is used for sanity check, so the bootloader will fail immediately if this value differs from runtime value. The value is used to determine max application size for updating. */
#define BOOTLOADER_SETTINGS_ADDRESS 0x0007F000 /**< The field specifies the page location of the bootloader settings address. */
#define BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS 0x0007E000 /**< The field specifies the page location of the mbr params page address. */
// Flash = 1024 KB
#elif defined(NRF52840_XXAA)
#define BOOTLOADER_REGION_START 0x000F4000 /**< This field should correspond to start address of the bootloader, found in UICR.RESERVED, 0x10001014, register. This value is used for sanity check, so the bootloader will fail immediately if this value differs from runtime value. The value is used to determine max application size for updating. */

@ -1 +1 @@
Subproject commit 55874813f82157b7509729b1a0c66e68f86e2d07
Subproject commit 23df777b301af128d3543e286cd865212214b44d

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840

View File

@ -67,24 +67,4 @@
#define USB_DESC_VID 0x239A
#define USB_DESC_UF2_PID 0x003B
#define USB_STRING_DESCRIPTORS { \
/* 0: is supported language = English */ \
TUD_DESC_STRCONV(0x0409), \
\
/* 1: Manufacturer */ \
TUD_DESC_STRCONV('E','l','e','c','t','r','o','n','u','t',' ','L','a','b','s'), \
\
/* 2: Product */ \
TUD_DESC_STRCONV('P','a','p','y','r', ' ', 'D','F','U'), \
\
/* 3: Serials TODO use chip ID */ \
usb_desc_str_serial, \
\
/* 4: CDC Interface */ \
TUD_DESC_STRCONV('P','a','p','y','r',' ','S','e','r','i','a','l'), \
\
/* 5: MSC Interface */ \
TUD_DESC_STRCONV('P','a','p','y','r',' ','U','F','2'), \
}
#endif // PPAPYR_H

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840

View File

@ -51,10 +51,10 @@
#define HWFC false
// Used as model string in OTA mode
#define BLEDIS_MANUFACTURER "Adafruit Industries"
#define BLEDIS_MODEL "Feather nRF52832"
#define BLEDIS_MANUFACTURER "Adafruit Industries"
#define BLEDIS_MODEL "Feather nRF52832"
#define UF2_PRODUCT_NAME "Adafruit Feather nRF52832"
#define UF2_INDEX_URL "https://www.adafruit.com/product/3406"
#define UF2_PRODUCT_NAME "Adafruit Feather nRF52832"
#define UF2_INDEX_URL "https://www.adafruit.com/product/3406"
#endif // _FEATHER_NRF52832_H

View File

@ -0,0 +1,2 @@
# nrf52 is nrf52832
MCU_SUB_VARIANT = nrf52

View File

@ -68,9 +68,9 @@
#define USB_DESC_CDC_ONLY_PID 0x002A
//------------- UF2 -------------//
#define UF2_PRODUCT_NAME "Adafruit Feather nRF52840 Express"
#define UF2_VOLUME_LABEL "FTHR840BOOT"
#define UF2_BOARD_ID "nRF52840-Feather-revD"
#define UF2_INDEX_URL "https://www.adafruit.com/product/4062"
#define UF2_PRODUCT_NAME "Adafruit Feather nRF52840 Express"
#define UF2_VOLUME_LABEL "FTHR840BOOT"
#define UF2_BOARD_ID "nRF52840-Feather-revD"
#define UF2_INDEX_URL "https://www.adafruit.com/product/4062"
#endif // _FEATHER_NRF52840_H

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52840

View File

@ -0,0 +1,61 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2018 Ha Thach for Adafruit Industries
*
* 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.
*/
#ifndef PCA10100_H
#define PCA10100_H
/*------------------------------------------------------------------*/
/* LED
*------------------------------------------------------------------*/
#define LEDS_NUMBER 2
#define LED_PRIMARY_PIN 13
#define LED_SECONDARY_PIN 14
#define LED_STATE_ON 0
/*------------------------------------------------------------------*/
/* BUTTON
*------------------------------------------------------------------*/
#define BUTTONS_NUMBER 2
#define BUTTON_1 11
#define BUTTON_2 12
#define BUTTON_PULL NRF_GPIO_PIN_PULLUP
/*------------------------------------------------------------------*/
/* UART
*------------------------------------------------------------------*/
#define RX_PIN_NUMBER 8
#define TX_PIN_NUMBER 6
#define CTS_PIN_NUMBER 0
#define RTS_PIN_NUMBER 0
#define HWFC false
// Used as model string in OTA mode
#define BLEDIS_MANUFACTURER "Nordic"
#define BLEDIS_MODEL "PCA10100"
#define UF2_PRODUCT_NAME "Nordic nRF52833 DK"
#define UF2_BOARD_ID "nRF52833-pca10100-v1"
#define UF2_INDEX_URL "https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52833-DK"
#endif // PCA10100_H

View File

@ -0,0 +1 @@
MCU_SUB_VARIANT = nrf52833

View File

@ -83,7 +83,7 @@
*/
#define ADAFRUIT_DEVICE_TYPE 0x0052
#ifdef NRF52840_XXAA
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA)
#define ADAFRUIT_DEV_REV 52840
#elif defined NRF52832_XXAA
#define ADAFRUIT_DEV_REV 0xADAF

View File

@ -44,9 +44,9 @@ void flash_nrf5x_flush (bool need_erase)
// - nRF52840 dfu serial/uf2 are USB-based which are DMA and should have no problems.
//
// Note: MSC uf2 does not erase page in advance like dfu serial
if ( need_erase ) nrf_nvmc_page_erase(_fl_addr);
if ( need_erase ) nrfx_nvmc_page_erase(_fl_addr);
nrf_nvmc_write_words(_fl_addr, (uint32_t *) _fl_buf, FLASH_PAGE_SIZE / 4);
nrfx_nvmc_words_write(_fl_addr, (uint32_t *) _fl_buf, FLASH_PAGE_SIZE / 4);
}
_fl_addr = FLASH_CACHE_INVALID_ADDR;

View File

@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "nrf_nvmc.h"
#include "nrfx_nvmc.h"
#ifdef __cplusplus
extern "C" {

View File

@ -0,0 +1,91 @@
/* Linker script to configure memory regions. */
SEARCH_DIR(.)
GROUP(-lgcc -lc -lnosys)
MEMORY
{
/** Flash start address for the bootloader. This setting will also be stored in UICR to allow the
* MBR to init the bootloader when starting the system. This value must correspond to
* BOOTLOADER_REGION_START found in dfu_types.h. The system is prevented from starting up if
* those values do not match. The check is performed in main.c, see
* APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
*/
FLASH (rx) : ORIGIN = 0x74000, LENGTH = 0x7E000-0x74000 /* 40 KB */
/** Location of mbr params page in flash. */
MBR_PARAMS_PAGE (rw) : ORIGIN = 0x0007E000, LENGTH = 0x1000
/** Location of bootloader setting in flash. */
BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x0007F000, LENGTH = 0x1000
/** RAM Region for bootloader. */
/* Avoid conflict with NOINIT for OTA bond sharing */
RAM (rwx) : ORIGIN = 0x20008000, LENGTH = 0x20020000-0x20008000
/* Location for double reset detection, no init */
DBL_RESET (rwx) : ORIGIN = 0x20007F7C, LENGTH = 0x04
/** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information
* from application to bootloader when using buttonluss DFU OTA. */
NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80
/** Location in UICR where bootloader start address is stored. */
UICR_BOOTLOADER (r) : ORIGIN = 0x10001014, LENGTH = 0x04
/** Location in UICR where mbr params page address is stored. */
UICR_MBR_PARAM_PAGE(r) : ORIGIN = 0x10001018, LENGTH = 0x04
}
SECTIONS
{
.fs_data_out ALIGN(4):
{
PROVIDE( __start_fs_data = .);
KEEP(*(fs_data))
PROVIDE( __stop_fs_data = .);
} = 0
/* Place the bootloader settings page in flash. */
.bootloaderSettings(NOLOAD) :
{
} > BOOTLOADER_SETTINGS
/* Write the bootloader address in UICR. */
.uicrBootStartAddress :
{
KEEP(*(.uicrBootStartAddress))
} > UICR_BOOTLOADER
/* Place the mbr params page in flash. */
.mbrParamsPage(NOLOAD) :
{
} > MBR_PARAMS_PAGE
/* Write the bootloader address in UICR. */
.uicrMbrParamsPageAddress :
{
KEEP(*(.uicrMbrParamsPageAddress))
} > UICR_MBR_PARAM_PAGE
.dbl_reset(NOLOAD) :
{
} > DBL_RESET
/* No init RAM section in bootloader. Used for bond information exchange. */
.noinit(NOLOAD) :
{
} > NOINIT
/* other placements follow here... */
}
INCLUDE "nrf_common.ld"

View File

@ -11,7 +11,15 @@ MEMORY
* those values do not match. The check is performed in main.c, see
* APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
*/
FLASH (rx) : ORIGIN = 0xF4000, LENGTH = 0xA000 /* 40 KB */
FLASH (rx) : ORIGIN = 0xF4000, LENGTH = 0xFE000-0xF4000 /* 40 KB */
/** Location of mbr params page in flash. */
MBR_PARAMS_PAGE (rw) : ORIGIN = 0xFE000, LENGTH = 0x1000
/** Location of bootloader setting in flash. */
BOOTLOADER_SETTINGS (rw) : ORIGIN = 0xFF000, LENGTH = 0x1000
/** RAM Region for bootloader. */
/* Avoid conflict with NOINIT for OTA bond sharing */
@ -21,20 +29,14 @@ MEMORY
DBL_RESET (rwx) : ORIGIN = 0x20007F7C, LENGTH = 0x04
/** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information
* from application to bootloader when using buttonluss DFU OTA.
*/
* from application to bootloader when using buttonluss DFU OTA. */
NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80
/** Location of bootloader setting in flash. */
BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x000FF000, LENGTH = 0x1000
/** Location in UICR where bootloader start address is stored. */
UICR_BOOTLOADER (r) : ORIGIN = 0x10001014, LENGTH = 0x04
/** Location of mbr params page in flash. */
MBR_PARAMS_PAGE (rw) : ORIGIN = 0x000FE000, LENGTH = 0x1000
/** Location in UICR where mbr params page address is stored. */
UICR_MBR_PARAM_PAGE(r) : ORIGIN = 0x10001018, LENGTH = 0x04
}

View File

@ -11,28 +11,31 @@ MEMORY
* those values do not match. The check is performed in main.c, see
* APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START);
*/
FLASH (rx) : ORIGIN = 0x74000, LENGTH = 0xA000 /* 40 KB */
FLASH (rx) : ORIGIN = 0x74000, LENGTH = 0x7E000-0x74000 /* 40 KB */
/** Location of mbr params page in flash. */
MBR_PARAMS_PAGE (rw) : ORIGIN = 0x7E000, LENGTH = 0x1000
/** Location of bootloader setting in flash. */
BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x7F000, LENGTH = 0x1000
/** RAM Region for bootloader. */
RAM (rwx) : ORIGIN = 0x20003000, LENGTH = 0x20007F7C-0x20003000
RAM (rwx) : ORIGIN = 0x20008000, LENGTH = 0x20010000-0x20008000
/* Location for double reset detection, no init */
DBL_RESET (rwx) : ORIGIN = 0x20007F7C, LENGTH = 0x04
/** Location of non initialized RAM. Non initialized RAM is used for exchanging bond information
* from application to bootloader when using buttonluss DFU OTA.
*/
* from application to bootloader when using buttonluss DFU OTA. */
NOINIT (rwx) : ORIGIN = 0x20007F80, LENGTH = 0x80
/** Location of bootloader setting in flash. */
BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x0007F000, LENGTH = 0x1000
/** Location in UICR where bootloader start address is stored. */
UICR_BOOTLOADER (r) : ORIGIN = 0x10001014, LENGTH = 0x04
/** Location of mbr params page in flash. */
MBR_PARAMS_PAGE (rw) : ORIGIN = 0x0007E000, LENGTH = 0x1000
/** Location in UICR where mbr params page address is stored. */
UICR_MBR_PARAM_PAGE(r) : ORIGIN = 0x10001018, LENGTH = 0x04
}

View File

@ -65,10 +65,10 @@
#include "pstorage_platform.h"
#include "nrf_mbr.h"
#include "pstorage.h"
#include "nrfx_nvmc.h"
#include "nrf_nvmc.h"
#ifdef NRF52840_XXAA
#ifdef NRF_USBD
#include "nrf_usbd.h"
#include "tusb.h"
@ -120,9 +120,12 @@ enum { BLE_CONN_CFG_HIGH_BANDWIDTH = 1 };
#define APPDATA_ADDR_START (BOOTLOADER_REGION_START-DFU_APP_DATA_RESERVED)
#ifdef NRF52840_XXAA
STATIC_ASSERT( APPDATA_ADDR_START == 0xED000);
// Flash 1024 KB
STATIC_ASSERT( APPDATA_ADDR_START == 0xED000);
#else
STATIC_ASSERT( APPDATA_ADDR_START == 0x6D000);
// Flash 512 KB
STATIC_ASSERT( APPDATA_ADDR_START == 0x6D000);
#endif
@ -275,11 +278,11 @@ void adafruit_factory_reset(void)
// clear all App Data if any
if ( DFU_APP_DATA_RESERVED )
{
nrf_nvmc_page_erase(APPDATA_ADDR_START);
nrfx_nvmc_page_erase(APPDATA_ADDR_START);
}
// Only need to erase the 1st page of Application code to make it invalid
nrf_nvmc_page_erase(DFU_BANK_0_REGION_START);
nrfx_nvmc_page_erase(DFU_BANK_0_REGION_START);
// back to normal
led_state(STATE_FACTORY_RESET_FINISHED);
@ -423,7 +426,7 @@ uint32_t proc_soc(void)
{
pstorage_sys_event_handler(soc_evt);
#ifdef NRF52840_XXAA
#ifdef NRF_USBD
extern void tusb_hal_nrf_power_event(uint32_t event);
/*------------- usb power event handler -------------*/
int32_t usbevt = (soc_evt == NRF_EVT_POWER_USB_DETECTED ) ? NRFX_POWER_USB_EVT_DETECTED:

View File

@ -2,13 +2,17 @@
#define NRFX_CONFIG_H__
// Power
#define NRFX_POWER_ENABLED 1
#define NRFX_POWER_CONFIG_IRQ_PRIORITY 7
#define NRFX_POWER_ENABLED 1
#define NRFX_POWER_DEFAULT_CONFIG_IRQ_PRIORITY 7
#define NRFX_CLOCK_ENABLED 0
#define NRFX_NVMC_ENABLED 1
// UART
#ifdef NRF52832_XXAA
#define NRFX_UART_ENABLED 1
#define NRFX_UART0_ENABLED 1
#define NRFX_UART_ENABLED 1
#define NRFX_UART0_ENABLED 1
#define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY 7
#define NRFX_UART_DEFAULT_CONFIG_HWFC NRF_UART_HWFC_DISABLED

View File

@ -45,38 +45,47 @@ int write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state)
// tinyusb callbacks
//--------------------------------------------------------------------+
// Invoked when received SCSI_CMD_INQUIRY
// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
{
(void) lun;
const char vid[] = "Adafruit";
const char pid[] = "nRF UF2";
const char rev[] = "1.0";
memcpy(vendor_id , vid, strlen(vid));
memcpy(product_id , pid, strlen(pid));
memcpy(product_rev, rev, strlen(rev));
}
// Invoked when received Test Unit Ready command.
// return true allowing host to read/write this LUN e.g SD card inserted
bool tud_msc_test_unit_ready_cb(uint8_t lun)
{
(void) lun;
return true;
}
// Callback invoked when received an SCSI command not in built-in list below
// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
// - READ10 and WRITE10 has their own callbacks
int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize)
{
void const* response = NULL;
int32_t resplen = 0;
memset(buffer, 0, bufsize);
uint16_t resplen = 0;
switch ( scsi_cmd[0] )
// most scsi handled is input
bool in_xfer = true;
switch (scsi_cmd[0])
{
case SCSI_CMD_TEST_UNIT_READY:
// Command that host uses to check our readiness before sending other commands
resplen = 0;
break;
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
// Host is about to read/write etc ... better not to disconnect disk
resplen = 0;
break;
case SCSI_CMD_START_STOP_UNIT:
// Host try to eject/safe remove/poweroff us. We could safely disconnect with disk storage, or go into lower power
/* scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd;
// Start bit = 0 : low power mode, if load_eject = 1 : unmount disk storage as well
// Start bit = 1 : Ready mode, if load_eject = 1 : mount disk storage
start_stop->start;
start_stop->load_eject;
*/
resplen = 0;
break;
default:
// Set Sense = Invalid Command Operation
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
@ -86,13 +95,18 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer,
break;
}
// return len must not larger than bufsize
if ( resplen > (int32_t)bufsize ) resplen = bufsize;
// return resplen must not larger than bufsize
if ( resplen > bufsize ) resplen = bufsize;
// copy response to stack's buffer if any
if ( response && resplen )
if ( response && (resplen > 0) )
{
memcpy(buffer, response, resplen);
if(in_xfer)
{
memcpy(buffer, response, resplen);
}else
{
// SCSI output
}
}
return resplen;
@ -161,6 +175,8 @@ void tud_msc_write10_complete_cb(uint8_t lun)
}
}
// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
// Application update block count and block size
void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
{
(void) lun;
@ -169,4 +185,26 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz
*block_size = 512;
}
// Invoked when received Start Stop Unit command
// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
// - Start = 1 : active mode, if load_eject = 1 : load disk storage
bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
{
(void) lun;
(void) power_condition;
if ( load_eject )
{
if (start)
{
// load disk storage
}else
{
// unload disk storage
}
}
return true;
}
#endif

View File

@ -58,11 +58,6 @@
//------------- Class enabled -------------//
#define CFG_TUD_CDC 1
#define CFG_TUD_MSC 1
#define CFG_TUD_HID_KEYBOARD 0
#define CFG_TUD_HID_MOUSE 0
#define CFG_TUD_HID_GENERIC 0 // not supported yet
#define CFG_TUD_CUSTOM_CLASS 0
/*------------------------------------------------------------------*/
/* CLASS DRIVER
@ -72,34 +67,15 @@
#define CFG_TUD_CDC_RX_BUFSIZE 1024
#define CFG_TUD_CDC_TX_BUFSIZE 1024
/* TX is sent automatically on every Start of Frame event ~ 1ms.
* If not enabled, application must call tud_cdc_flush() periodically
* Note: Enabled this could overflow device task, if it does, define
* CFG_TUD_TASK_QUEUE_SZ with large value
*/
#define CFG_TUD_CDC_FLUSH_ON_SOF 0
// Number of supported Logical Unit Number
#define CFG_TUD_MSC_MAXLUN 1
// Buffer size for each read/write transfer, the more the better
#define CFG_TUD_MSC_BUFSIZE (4*1024)
// Vendor name included in Inquiry response, max 8 bytes
#define CFG_TUD_MSC_VENDOR "Adafruit"
// Product name included in Inquiry response, max 16 bytes
#define CFG_TUD_MSC_PRODUCT "Feather nRF52840"
// Product revision string included in Inquiry response, max 4 bytes
#define CFG_TUD_MSC_PRODUCT_REV "1.0"
//--------------------------------------------------------------------+
// USB RAM PLACEMENT
//--------------------------------------------------------------------+
#define CFG_TUSB_ATTR_USBRAM
#define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4)
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#define BREAKPOINT_IGNORE_COUNT(n) \

View File

@ -40,13 +40,6 @@
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
// from usb_desc.c for dynamic descriptor
extern tusb_desc_device_t usb_desc_dev;
extern usb_desc_cfg_t usb_desc_cfg;
// Serial string using unique Device ID
extern uint16_t usb_desc_str_serial[1+16];
/* tinyusb function that handles power event (detected, ready, removed)
* We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. */
extern void tusb_hal_nrf_power_event(uint32_t event);
@ -94,26 +87,9 @@ void usb_init(bool cdc_only)
tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY);
}
if ( cdc_only )
{
// Change PID to CDC only
usb_desc_dev.idProduct = USB_DESC_CDC_ONLY_PID;
usb_desc_init(cdc_only);
// Remove MSC interface = reduce total interface + adjust config desc length
usb_desc_cfg.config.bNumInterfaces--;
usb_desc_cfg.config.wTotalLength -= sizeof(usb_desc_cfg.msc);
}
// Create Serial string descriptor
char tmp_serial[17];
sprintf(tmp_serial, "%08lX%08lX", NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0]);
for(uint8_t i=0; i<16; i++)
{
usb_desc_str_serial[1+i] = tmp_serial[i];
}
// Init tusb stack
// Init TinyUSB stack
tusb_init();
}
@ -124,7 +100,7 @@ void usb_teardown(void)
// Abort all transfers
// Disable pull up
nrf_usbd_pullup_disable();
nrf_usbd_pullup_disable(NRF_USBD);
// Disable Interrupt
NVIC_DisableIRQ(USBD_IRQn);
@ -132,7 +108,7 @@ void usb_teardown(void)
// disable all interrupt
NRF_USBD->INTENCLR = NRF_USBD->INTEN;
nrf_usbd_disable();
nrf_usbd_disable(NRF_USBD);
sd_clock_hfclk_release();
sd_power_usbdetected_enable(false);

View File

@ -24,15 +24,6 @@
#include "usb_desc.h"
/*------------- Interface Numbering -------------*/
enum {
ITF_NUM_CDC = 0 ,
ITF_NUM_CDC_DATA ,
ITF_NUM_MSC ,
ITF_NUM_TOTAL
};
enum {
ITF_STR_LANGUAGE = 0 ,
ITF_STR_MANUFACTURER ,
@ -42,59 +33,16 @@ enum {
ITF_STR_MSC
};
/*------------- Endpoint Numbering & Size -------------*/
#define _EP_IN(x) (0x80 | (x))
#define _EP_OUT(x) (x)
// CDC
#define EP_CDC_NOTIF _EP_IN ( ITF_NUM_CDC+1 )
#define EP_CDC_NOTIF_SIZE 8
#define EP_CDC_OUT _EP_OUT( ITF_NUM_CDC+2 )
#define EP_CDC_IN _EP_IN ( ITF_NUM_CDC+2 )
// Mass Storage
#define EP_MSC_OUT _EP_OUT( ITF_NUM_MSC+1 )
#define EP_MSC_IN _EP_IN ( ITF_NUM_MSC+1 )
#define EP_MSC_SIZE 64
//--------------------------------------------------------------------+
// STRING DESCRIPTORS
//--------------------------------------------------------------------+
#ifndef USB_STRING_DESCRIPTORS
#define USB_STRING_DESCRIPTORS { \
/* 0: is supported language = English */ \
TUD_DESC_STRCONV(0x0409), \
\
/* 1: Manufacturer */ \
TUD_DESC_STRCONV('A','d','a','f','r','u','i','t',' ','I','n','d','u','s','t','r','i','e','s'), \
\
/* 2: Product */ \
TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','n','R','F','5','2','8','4','0', ' ', 'D','F','U'), \
\
/* 3: Serials TODO use chip ID */ \
usb_desc_str_serial, \
\
/* 4: CDC Interface */ \
TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','S','e','r','i','a','l'), \
\
/* 5: MSC Interface */ \
TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','U','F','2'), \
}
#endif
// CDC + MSC or CDC only mode
static bool _cdc_only = false;
// Serial is 64-bit DeviceID -> 16 chars len
uint16_t usb_desc_str_serial[1+16] = { TUD_DESC_STR_HEADER(16) };
// array of pointer to string descriptors
uint16_t const * const string_desc_arr [] = USB_STRING_DESCRIPTORS;
static char desc_str_serial[1+16];
//--------------------------------------------------------------------+
// Device Descriptor
//--------------------------------------------------------------------+
tusb_desc_device_t usb_desc_dev =
tusb_desc_device_t desc_device =
{
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
@ -118,187 +66,117 @@ tusb_desc_device_t usb_desc_dev =
.bNumConfigurations = 0x01
};
// Invoked when received GET DEVICE DESCRIPTOR
// Application return pointer to descriptor
uint8_t const * tud_descriptor_device_cb(void)
{
return (uint8_t const *) &desc_device;
}
//--------------------------------------------------------------------+
// Configuration Descriptor
//--------------------------------------------------------------------+
usb_desc_cfg_t usb_desc_cfg =
enum {
ITF_NUM_CDC = 0 ,
ITF_NUM_CDC_DATA ,
ITF_NUM_MSC ,
ITF_NUM_TOTAL
};
uint8_t const desc_configuration_cdc_msc[] =
{
.config =
{
.bLength = sizeof(tusb_desc_configuration_t),
.bDescriptorType = TUSB_DESC_CONFIGURATION,
.wTotalLength = sizeof(usb_desc_cfg_t),
.bNumInterfaces = ITF_NUM_TOTAL,
.bConfigurationValue = 1,
.iConfiguration = 0x00,
.bmAttributes = TUSB_DESC_CONFIG_ATT_BUS_POWER,
.bMaxPower = TUSB_DESC_CONFIG_POWER_MA(100)
},
// Interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// IAD points to CDC Interfaces
.cdc =
{
.iad =
{
.bLength = sizeof(tusb_desc_interface_assoc_t),
.bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION,
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, ITF_STR_CDC, 0x81, 8, 0x02, 0x82, 64),
.bFirstInterface = ITF_NUM_CDC,
.bInterfaceCount = 2,
// Interface number, string index, EP Out & EP In address, EP size
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, ITF_STR_MSC, 0x03, 0x83, 64),
};
.bFunctionClass = TUSB_CLASS_CDC,
.bFunctionSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL,
.bFunctionProtocol = CDC_COMM_PROTOCOL_ATCOMMAND,
.iFunction = 0
},
uint8_t const desc_configuration_cdc_only[] =
{
// Interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL-1, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
//------------- CDC Communication Interface -------------//
.comm_itf =
{
.bLength = sizeof(tusb_desc_interface_t),
.bDescriptorType = TUSB_DESC_INTERFACE,
.bInterfaceNumber = ITF_NUM_CDC,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = TUSB_CLASS_CDC,
.bInterfaceSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL,
.bInterfaceProtocol = CDC_COMM_PROTOCOL_ATCOMMAND,
.iInterface = ITF_STR_CDC
},
.header =
{
.bLength = sizeof(cdc_desc_func_header_t),
.bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
.bDescriptorSubType = CDC_FUNC_DESC_HEADER,
.bcdCDC = 0x0120
},
.call =
{
.bLength = sizeof(cdc_desc_func_call_management_t),
.bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
.bDescriptorSubType = CDC_FUNC_DESC_CALL_MANAGEMENT,
.bmCapabilities = { 0 },
.bDataInterface = ITF_NUM_CDC+1,
},
.acm =
{
.bLength = sizeof(cdc_desc_func_acm_t),
.bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
.bDescriptorSubType = CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT,
.bmCapabilities = { // 0x02
.support_line_request = 1,
}
},
.union_func =
{
.bLength = sizeof(cdc_desc_func_union_t), // plus number of
.bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
.bDescriptorSubType = CDC_FUNC_DESC_UNION,
.bControlInterface = ITF_NUM_CDC,
.bSubordinateInterface = ITF_NUM_CDC+1,
},
.ep_notif =
{
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = EP_CDC_NOTIF,
.bmAttributes = { .xfer = TUSB_XFER_INTERRUPT },
.wMaxPacketSize = { .size = EP_CDC_NOTIF_SIZE },
.bInterval = 0x10
},
//------------- CDC Data Interface -------------//
.data_itf =
{
.bLength = sizeof(tusb_desc_interface_t),
.bDescriptorType = TUSB_DESC_INTERFACE,
.bInterfaceNumber = ITF_NUM_CDC+1,
.bAlternateSetting = 0x00,
.bNumEndpoints = 2,
.bInterfaceClass = TUSB_CLASS_CDC_DATA,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.iInterface = 0x00
},
.ep_out =
{
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = EP_CDC_OUT,
.bmAttributes = { .xfer = TUSB_XFER_BULK },
.wMaxPacketSize = { .size = CFG_TUD_CDC_EPSIZE },
.bInterval = 0
},
.ep_in =
{
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = EP_CDC_IN,
.bmAttributes = { .xfer = TUSB_XFER_BULK },
.wMaxPacketSize = { .size = CFG_TUD_CDC_EPSIZE },
.bInterval = 0
},
},
//------------- Mass Storage-------------//
.msc =
{
.itf =
{
.bLength = sizeof(tusb_desc_interface_t),
.bDescriptorType = TUSB_DESC_INTERFACE,
.bInterfaceNumber = ITF_NUM_MSC,
.bAlternateSetting = 0x00,
.bNumEndpoints = 2,
.bInterfaceClass = TUSB_CLASS_MSC,
.bInterfaceSubClass = MSC_SUBCLASS_SCSI,
.bInterfaceProtocol = MSC_PROTOCOL_BOT,
.iInterface = ITF_STR_MSC
},
.ep_out =
{
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = EP_MSC_OUT,
.bmAttributes = { .xfer = TUSB_XFER_BULK },
.wMaxPacketSize = { .size = EP_MSC_SIZE},
.bInterval = 1
},
.ep_in =
{
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = EP_MSC_IN,
.bmAttributes = { .xfer = TUSB_XFER_BULK },
.wMaxPacketSize = { .size = EP_MSC_SIZE },
.bInterval = 1
}
}
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, ITF_STR_CDC, 0x81, 8, 0x02, 0x82, 64),
};
// tud_desc_set is required by tinyusb stack
// since CFG_TUD_DESC_AUTO is enabled, we only need to set string_arr
tud_desc_set_t tud_desc_set =
// Invoked when received GET CONFIGURATION DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
{
.device = &usb_desc_dev,
.config = &usb_desc_cfg,
.string_arr = (uint8_t const **) string_desc_arr,
.string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]),
(void) index; // for multiple configurations
return _cdc_only ? desc_configuration_cdc_only : desc_configuration_cdc_msc;
}
.hid_report =
{
.generic = NULL,
.boot_keyboard = NULL,
.boot_mouse = NULL
}
// Enumerate as CDC + MSC or CDC only
void usb_desc_init(bool cdc_only)
{
_cdc_only = cdc_only;
if ( cdc_only )
{
// Change PID to CDC only
desc_device.idProduct = USB_DESC_CDC_ONLY_PID;
}
// Create Serial string descriptor
sprintf(desc_str_serial, "%08lX%08lX", NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0]);
}
//--------------------------------------------------------------------+
// STRING DESCRIPTORS
//--------------------------------------------------------------------+
// array of pointer to string descriptors
char const* string_desc_arr [] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
BLEDIS_MANUFACTURER, // 1: Manufacturer
BLEDIS_MODEL, // 2: Product
desc_str_serial, // 3: Serials, should use chip ID
"nRF Serial", // 4: CDC Interface
"nRF UF2", // 5: MSC Interface
};
// up to 64 unicode characters
static uint16_t _desc_str[64+1];
// Invoked when received GET STRING DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
uint16_t const* tud_descriptor_string_cb(uint8_t index)
{
uint8_t chr_count;
if ( index == 0)
{
memcpy(&_desc_str[1], string_desc_arr[0], 2);
chr_count = 1;
}else
{
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
// Convert ASCII string into UTF-16
const char* str = string_desc_arr[index];
// Cap at max char
chr_count = strlen(str);
if ( chr_count > 31 ) chr_count = 31;
for(uint8_t i=0; i<chr_count; i++)
{
_desc_str[1+i] = str[i];
}
}
// first byte is length (including header), second byte is string type
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
return _desc_str;
}

View File

@ -28,59 +28,18 @@
#include "tusb.h"
#include "boards.h"
#ifdef __cplusplus
extern "C" {
#endif
void usb_desc_init(bool cdc_only);
#ifndef USB_DESC_VID
#define USB_DESC_VID 0x239A
#define USB_DESC_VID 0x239A
#endif
#ifndef USB_DESC_UF2_PID
#define USB_DESC_UF2_PID 0x0029
#define USB_DESC_UF2_PID 0x0029
#endif
#ifndef USB_DESC_CDC_ONLY_PID
#define USB_DESC_CDC_ONLY_PID 0x002A
#endif
/*------------- Configuration Descriptor -------------*/
typedef struct ATTR_PACKED
{
tusb_desc_configuration_t config;
//------------- CDC -------------//
struct ATTR_PACKED
{
tusb_desc_interface_assoc_t iad;
//CDC Control Interface
tusb_desc_interface_t comm_itf;
cdc_desc_func_header_t header;
cdc_desc_func_call_management_t call;
cdc_desc_func_acm_t acm;
cdc_desc_func_union_t union_func;
tusb_desc_endpoint_t ep_notif;
//CDC Data Interface
tusb_desc_interface_t data_itf;
tusb_desc_endpoint_t ep_out;
tusb_desc_endpoint_t ep_in;
}cdc;
//------------- Mass Storage -------------//
struct ATTR_PACKED
{
tusb_desc_interface_t itf;
tusb_desc_endpoint_t ep_out;
tusb_desc_endpoint_t ep_in;
} msc;
} usb_desc_cfg_t;
#ifdef __cplusplus
}
#define USB_DESC_CDC_ONLY_PID 0x002A
#endif
#endif /* USB_DESC_H_ */