diff --git a/examples/device/nrf52840/src/msc_device_app.c b/examples/device/nrf52840/src/msc_device_app.c index 1730975d..5fc3f20f 100644 --- a/examples/device/nrf52840/src/msc_device_app.c +++ b/examples/device/nrf52840/src/msc_device_app.c @@ -98,47 +98,62 @@ void msc_app_umount(uint8_t rhport) } -msc_csw_status_t tud_msc_scsi_cb (uint8_t rhport, uint8_t lun, uint8_t scsi_cmd[16], void const ** pp_buffer, uint16_t* p_length) +bool tud_msc_scsi_cb (uint8_t rhport, uint8_t lun, uint8_t scsi_cmd[16], void* buffer, uint16_t* p_len) { // read10 & write10 has their own callback and MUST not be handled here + + void* bufptr = NULL; + uint16_t buflen = 0; + switch (scsi_cmd[0]) { case SCSI_CMD_INQUIRY: - (*pp_buffer) = &mscd_inquiry_data; - (*p_length) = sizeof(scsi_inquiry_data_t); + bufptr = &mscd_inquiry_data; + buflen = sizeof(scsi_inquiry_data_t); break; case SCSI_CMD_READ_CAPACITY_10: - (*pp_buffer) = &mscd_read_capacity10_data; - (*p_length) = sizeof(scsi_read_capacity10_data_t); + bufptr = &mscd_read_capacity10_data; + buflen = sizeof(scsi_read_capacity10_data_t); break; case SCSI_CMD_REQUEST_SENSE: - (*pp_buffer) = &mscd_sense_data; - (*p_length) = sizeof(scsi_sense_fixed_data_t); + bufptr = &mscd_sense_data; + buflen = sizeof(scsi_sense_fixed_data_t); break; case SCSI_CMD_READ_FORMAT_CAPACITY: - (*pp_buffer) = &mscd_format_capacity_data; - (*p_length) = sizeof(scsi_read_format_capacity_data_t); + bufptr = &mscd_format_capacity_data; + buflen = sizeof(scsi_read_format_capacity_data_t); break; case SCSI_CMD_MODE_SENSE_6: - (*pp_buffer) = &msc_dev_mode_para; - (*p_length) = sizeof(msc_dev_mode_para); + bufptr = &msc_dev_mode_para; + buflen = sizeof(msc_dev_mode_para); break; case SCSI_CMD_TEST_UNIT_READY: - (*pp_buffer) = NULL; - (*p_length) = 0; + bufptr = NULL; + buflen= 0; break; case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: - (*pp_buffer) = NULL; - (*p_length) = 0; + bufptr = NULL; + buflen= 0; break; - default: return MSC_CSW_STATUS_FAILED; + default: + (*p_len) = 0; + return false; + } + + if ( bufptr && buflen ) + { + // Response len must not larger than expected from host + TU_ASSERT( (*p_len) >= buflen ); + + memcpy(buffer, bufptr, buflen); + (*p_len) = buflen; } //------------- clear sense data if it is not request sense command -------------// @@ -149,7 +164,7 @@ msc_csw_status_t tud_msc_scsi_cb (uint8_t rhport, uint8_t lun, uint8_t scsi_cmd[ mscd_sense_data.additional_sense_qualifier = 0; } - return MSC_CSW_STATUS_PASSED; + return true; } //--------------------------------------------------------------------+ diff --git a/examples/device/nrf52840/src/msc_device_ramdisk.c b/examples/device/nrf52840/src/msc_device_ramdisk.c index bb9c53e4..8e34942d 100644 --- a/examples/device/nrf52840/src/msc_device_ramdisk.c +++ b/examples/device/nrf52840/src/msc_device_ramdisk.c @@ -91,13 +91,13 @@ uint8_t msc_device_ramdisk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = //--------------------------------------------------------------------+ // IMPLEMENTATION //--------------------------------------------------------------------+ -uint16_t tud_msc_read10_cb (uint8_t rhport, uint8_t lun, void** pp_buffer, uint32_t lba, uint16_t block_count) +uint16_t tud_msc_read10_cb (uint8_t rhport, uint8_t lun, uint32_t lba, uint16_t block_count, void** pp_buffer) { (*pp_buffer) = msc_device_ramdisk[lba]; return min16_of(block_count, DISK_BLOCK_NUM); } -uint16_t tud_msc_write10_cb(uint8_t rhport, uint8_t lun, void** pp_buffer, uint32_t lba, uint16_t block_count) +uint16_t tud_msc_write10_cb(uint8_t rhport, uint8_t lun, uint32_t lba, uint16_t block_count, void** pp_buffer) { (*pp_buffer) = msc_device_ramdisk[lba]; diff --git a/examples/device/nrf52840/src/tusb_config.h b/examples/device/nrf52840/src/tusb_config.h index a885ab89..86e3698f 100644 --- a/examples/device/nrf52840/src/tusb_config.h +++ b/examples/device/nrf52840/src/tusb_config.h @@ -46,10 +46,14 @@ //--------------------------------------------------------------------+ // CONTROLLER CONFIGURATION //--------------------------------------------------------------------+ -//#define CFG_TUSB_MCU will be passed from IDE/command line for easy board/mcu switching +#define CFG_TUSB_MCU OPT_MCU_NRF5X +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE + +#define CFG_TUSB_DEBUG 2 + +#define CFG_TUSB_OS OPT_OS_NONE // be passed from IDE/command line for easy project switching +//#define CFG_TUD_TASK_PRIO 0 // be passed from IDE/command line for easy project switching -#define CFG_TUSB_MCU OPT_MCU_NRF5X -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE) //--------------------------------------------------------------------+ // DEVICE CONFIGURATION @@ -63,27 +67,24 @@ #define CFG_TUD_MSC 1 #define CFG_TUD_CDC 1 -//--------------------------------------------------------------------+ -// COMMON CONFIGURATION -//--------------------------------------------------------------------+ -#define CFG_TUSB_DEBUG 2 +/*------------------------------------------------------------------*/ +/* CLASS DRIVER + *------------------------------------------------------------------*/ + +// FIFO size of CDC TX and RX +#define CFG_TUD_CDC_BUFSIZE 64 + +// TX is sent automatically every Start of Frame event. +// If not enabled, application must call tud_cdc_flush() periodically +#define CFG_TUD_CDC_FLUSH_ON_SOF 1 -#define CFG_TUSB_OS OPT_OS_NONE // be passed from IDE/command line for easy project switching -//#define CFG_TUD_TASK_PRIO 0 // be passed from IDE/command line for easy project switching //--------------------------------------------------------------------+ // USB RAM PLACEMENT //--------------------------------------------------------------------+ #define CFG_TUSB_ATTR_USBRAM +#define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4) -// LPC11uxx and LPC13uxx requires each buffer has to be 64-byte alignment -#if CFG_TUSB_MCU == OPT_MCU_LPC11UXX || CFG_TUSB_MCU == OPT_MCU_LPC13UXX - #define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(64) -#elif CFG_TUSB_MCU == OPT_MCU_NRF5X - #define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4) -#else - #define CFG_TUSB_MEM_ALIGN -#endif #ifdef __cplusplus } diff --git a/hw/mcu/nordic/nrf52/sdk/drivers_nrf/usbd/nrf_drv_usbd_errata.h b/hw/mcu/nordic/nrf52/sdk/drivers_nrf/usbd/nrf_drv_usbd_errata.h index 00371e96..ad24f3c8 100644 --- a/hw/mcu/nordic/nrf52/sdk/drivers_nrf/usbd/nrf_drv_usbd_errata.h +++ b/hw/mcu/nordic/nrf52/sdk/drivers_nrf/usbd/nrf_drv_usbd_errata.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2017 - 2017, Nordic Semiconductor ASA + * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA * * All rights reserved. * @@ -85,6 +85,19 @@ static inline bool nrf_drv_usbd_errata_type_52840_proto1(void) ( ((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00 ) ); } +/** + * @brief Internal auxiliary function to check if the program is running on first final product of + * NRF52840 chip + * @retval true It is NRF52480 chip and it is first final product + * @retval false It is other chip + */ +static inline bool nrf_drv_usbd_errata_type_52840_fp1(void) +{ + return ( nrf_drv_usbd_errata_type_52840() && + ( ((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x10 ) && + ( ((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00 ) ); +} + /** * @brief Function to check if chip requires errata 104 * @@ -124,6 +137,32 @@ static inline bool nrf_drv_usbd_errata_166(void) return NRF_DRV_USBD_ERRATA_ENABLE && true; } +/** + * @brief Function to check if chip requires errata 171 + * + * Errata: USBD might not reach its active state. + * + * @retval true Errata should be implemented + * @retval false Errata should not be implemented + */ +static inline bool nrf_drv_usbd_errata_171(void) +{ + return NRF_DRV_USBD_ERRATA_ENABLE && true; +} + +/** + * @brief Function to check if chip requires errata 187 + * + * Errata: USB cannot be enabled + * + * @retval true Errata should be implemented + * @retval false Errata should not be implemented + */ +static inline bool nrf_drv_usbd_errata_187(void) +{ + return NRF_DRV_USBD_ERRATA_ENABLE && nrf_drv_usbd_errata_type_52840_fp1(); +} + /** * @brief Function to check if chip requires errata ??? * @@ -137,5 +176,18 @@ static inline bool nrf_drv_usbd_errata_sizeepout_rw(void) return NRF_DRV_USBD_ERRATA_ENABLE && nrf_drv_usbd_errata_type_52840_proto1(); } +/** + * @brief Function to check if chip requires errata 199 + * + * Errata: USBD cannot receive tasks during DMA + * + * @retval true Errata should be implemented + * @retval false Errata should not be implemented + */ +static inline bool nrf_drv_usb_errata_199(void) +{ + return NRF_DRV_USBD_ERRATA_ENABLE && true; +} + /** @} */ #endif /* NRF_DRV_USBD_ERRATA_H__ */ diff --git a/tinyusb/portable/nordic/nrf5x/hal_nrf5x.c b/tinyusb/portable/nordic/nrf5x/hal_nrf5x.c index f77bdaa1..16ceb0bc 100644 --- a/tinyusb/portable/nordic/nrf5x/hal_nrf5x.c +++ b/tinyusb/portable/nordic/nrf5x/hal_nrf5x.c @@ -60,17 +60,6 @@ #define USB_NVIC_PRIO 7 -// TODO must cover SD present but not enabled -#ifdef SOFTDEVICE_PRESENT -#define POWER_DETECT NRF_EVT_POWER_USB_DETECTED -#define POWER_READY NRF_EVT_POWER_USB_POWER_READY -#define POWER_REMOVE NRF_EVT_POWER_USB_REMOVED -#else -#define POWER_DETECT NRF_DRV_POWER_USB_EVT_DETECTED -#define POWER_READY NRF_DRV_POWER_USB_EVT_READY -#define POWER_REMOVE NRF_DRV_POWER_USB_EVT_REMOVED -#endif - /*------------------------------------------------------------------*/ /* FUNCTION DECLARATION *------------------------------------------------------------------*/ @@ -115,19 +104,16 @@ bool tusb_hal_init(void) // power_usb_event_handler must be called by SOC event hanlder return true; - } + }else #endif - -#if 0 - // USB Power detection - const nrf_drv_power_usbevt_config_t config = { - .handler = power_usb_event_handler - }; - return ( NRF_SUCCESS == nrf_drv_power_usbevt_init(&config) ); -#else - return true; // TODO remove -#endif + // USB Power detection + const nrf_drv_power_usbevt_config_t config = + { + .handler = (nrf_drv_power_usb_event_handler_t) power_usb_event_handler + }; + return ( NRF_SUCCESS == nrf_drv_power_usbevt_init(&config) ); + } } void tusb_hal_int_enable(uint8_t rhport) @@ -195,146 +181,161 @@ static void hfclk_disable(void) *------------------------------------------------------------------*/ void power_usb_event_handler(uint32_t event) { - switch ( event ) + uint32_t POWER_DETECT, POWER_READY, POWER_REMOVE; + +#ifdef SOFTDEVICE_PRESENT + if ( is_sd_enabled() ) { - case POWER_DETECT: - if ( !NRF_USBD->ENABLE ) - { - /* Prepare for READY event receiving */ - nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK); + POWER_DETECT = NRF_EVT_POWER_USB_DETECTED; + POWER_READY = NRF_EVT_POWER_USB_POWER_READY; + POWER_REMOVE = NRF_EVT_POWER_USB_REMOVED; + }else +#endif + { + POWER_DETECT = NRF_DRV_POWER_USB_EVT_DETECTED; + POWER_READY = NRF_DRV_POWER_USB_EVT_READY; + POWER_REMOVE = NRF_DRV_POWER_USB_EVT_REMOVED; + } - /* Enable the peripheral */ - // ERRATA 171, 187 - - if (nrf_drv_usbd_errata_187()) - { -// CRITICAL_REGION_ENTER(); - if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) - { - *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; - *((volatile uint32_t *)(0x4006ED14)) = 0x00000003; - *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; - } - else - { - *((volatile uint32_t *)(0x4006ED14)) = 0x00000003; - } -// CRITICAL_REGION_EXIT(); - } - - if (nrf_drv_usbd_errata_171()) - { -// CRITICAL_REGION_ENTER(); - if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) - { - *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; - *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0; - *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; - } - else - { - *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0; - } -// CRITICAL_REGION_EXIT(); - } - - nrf_usbd_enable(); - - // Enable HFCLK - hfclk_enable(); - } - break; - - case POWER_READY: - /* Waiting for USBD peripheral enabled */ - while ( !(NRF_USBD_EVENTCAUSE_READY_MASK & NRF_USBD->EVENTCAUSE) ) { } + if ( POWER_DETECT == event ) + { + if ( !NRF_USBD->ENABLE ) + { + /* Prepare for READY event receiving */ nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK); - nrf_usbd_event_clear(NRF_USBD_EVENT_USBEVENT); - if (nrf_drv_usbd_errata_171()) - { -// CRITICAL_REGION_ENTER(); - if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) - { - *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; - *((volatile uint32_t *)(0x4006EC14)) = 0x00000000; - *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; - } - else - { - *((volatile uint32_t *)(0x4006EC14)) = 0x00000000; - } - -// CRITICAL_REGION_EXIT(); - } + /* Enable the peripheral */ + // ERRATA 171, 187 if (nrf_drv_usbd_errata_187()) { // CRITICAL_REGION_ENTER(); - if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) - { - *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; - *((volatile uint32_t *)(0x4006ED14)) = 0x00000000; - *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; - } - else - { - *((volatile uint32_t *)(0x4006ED14)) = 0x00000000; - } + if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) + { + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + *((volatile uint32_t *)(0x4006ED14)) = 0x00000003; + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + } + else + { + *((volatile uint32_t *)(0x4006ED14)) = 0x00000003; + } // CRITICAL_REGION_EXIT(); } - if ( nrf_drv_usbd_errata_166() ) + if (nrf_drv_usbd_errata_171()) { - *((volatile uint32_t *) (NRF_USBD_BASE + 0x800)) = 0x7E3; - *((volatile uint32_t *) (NRF_USBD_BASE + 0x804)) = 0x40; - - __ISB(); __DSB(); +// CRITICAL_REGION_ENTER(); + if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) + { + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0; + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + } + else + { + *((volatile uint32_t *)(0x4006EC14)) = 0x000000C0; + } +// CRITICAL_REGION_EXIT(); } - nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half); + nrf_usbd_enable(); - // Enable interrupt. SOF is used as CDC auto flush - NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_ACCESSFAULT_Msk | - USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk | - USBD_INTEN_EPDATA_Msk | USBD_INTEN_SOF_Msk; + // Enable HFCLK + hfclk_enable(); + } + } + else if ( POWER_READY == event ) +{ + /* Waiting for USBD peripheral enabled */ + while ( !(NRF_USBD_EVENTCAUSE_READY_MASK & NRF_USBD->EVENTCAUSE) ) { } + nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK); + nrf_usbd_event_clear(NRF_USBD_EVENT_USBEVENT); - // FIXME Errata 104: USB complete event is not generated (happedn randomly). - // Requires to enable SOF to perform clean up task. - // nrf_drv_usbd_errata_104() + if (nrf_drv_usbd_errata_171()) + { +// CRITICAL_REGION_ENTER(); + if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) + { + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + *((volatile uint32_t *)(0x4006EC14)) = 0x00000000; + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + } + else + { + *((volatile uint32_t *)(0x4006EC14)) = 0x00000000; + } - // Enable interrupt, Priorities 0,1,4,5 (nRF52) are reserved for SoftDevice - NVIC_SetPriority(USBD_IRQn, USB_NVIC_PRIO); - NVIC_ClearPendingIRQ(USBD_IRQn); - NVIC_EnableIRQ(USBD_IRQn); +// CRITICAL_REGION_EXIT(); + } - // Wait for HFCLK - while ( !hfclk_running() ) {} + if (nrf_drv_usbd_errata_187()) + { +// CRITICAL_REGION_ENTER(); + if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000) + { + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + *((volatile uint32_t *)(0x4006ED14)) = 0x00000000; + *((volatile uint32_t *)(0x4006EC00)) = 0x00009375; + } + else + { + *((volatile uint32_t *)(0x4006ED14)) = 0x00000000; + } +// CRITICAL_REGION_EXIT(); + } - // Enable pull up - nrf_usbd_pullup_enable(); - break; + if ( nrf_drv_usbd_errata_166() ) + { + *((volatile uint32_t *) (NRF_USBD_BASE + 0x800)) = 0x7E3; + *((volatile uint32_t *) (NRF_USBD_BASE + 0x804)) = 0x40; - case POWER_REMOVE: - if ( NRF_USBD->ENABLE ) - { - // Abort all transfers + __ISB(); __DSB(); + } - // Disable pull up - nrf_usbd_pullup_disable(); + nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half); - // Disable Interrupt - NVIC_DisableIRQ(USBD_IRQn); + // Enable interrupt. SOF is used as CDC auto flush + NRF_USBD->INTENSET = USBD_INTEN_USBRESET_Msk | USBD_INTEN_USBEVENT_Msk | USBD_INTEN_ACCESSFAULT_Msk | + USBD_INTEN_EP0SETUP_Msk | USBD_INTEN_EP0DATADONE_Msk | USBD_INTEN_ENDEPIN0_Msk | USBD_INTEN_ENDEPOUT0_Msk | + USBD_INTEN_EPDATA_Msk | USBD_INTEN_SOF_Msk; - // disable all interrupt - NRF_USBD->INTENCLR = NRF_USBD->INTEN; + // FIXME Errata 104: USB complete event is not generated (happedn randomly). + // Requires to enable SOF to perform clean up task. + // nrf_drv_usbd_errata_104() - nrf_usbd_disable(); - hfclk_disable(); - } - break; + // Enable interrupt, Priorities 0,1,4,5 (nRF52) are reserved for SoftDevice + NVIC_SetPriority(USBD_IRQn, USB_NVIC_PRIO); + NVIC_ClearPendingIRQ(USBD_IRQn); + NVIC_EnableIRQ(USBD_IRQn); - default: break; + // Wait for HFCLK + while ( !hfclk_running() ) {} + + // Enable pull up + nrf_usbd_pullup_enable(); + } + else if (POWER_REMOVE == event ) + { + if ( NRF_USBD->ENABLE ) + { + // Abort all transfers + + // Disable pull up + nrf_usbd_pullup_disable(); + + // Disable Interrupt + NVIC_DisableIRQ(USBD_IRQn); + + // disable all interrupt + NRF_USBD->INTENCLR = NRF_USBD->INTEN; + + nrf_usbd_disable(); + hfclk_disable(); + } + } + else + { } }