hathach 8 лет назад
Родитель
Сommit
8c0a5f7d3b

+ 32 - 17
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;
 }
 
 //--------------------------------------------------------------------+

+ 2 - 2
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];
 

+ 18 - 17
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
  }

+ 53 - 1
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__ */

+ 133 - 132
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 ( POWER_DETECT == event )
+  {
+    if ( !NRF_USBD->ENABLE )
+    {
+      /* Prepare for READY event receiving */
+      nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK);
 
-        if (nrf_drv_usbd_errata_187())
-        {
+      /* 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 (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
+        {
+          *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
+          *((volatile uint32_t *)(0x4006ED14)) = 0x00000003;
+          *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
         }
-
-        if (nrf_drv_usbd_errata_171())
+        else
         {
-//          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();
+          *((volatile uint32_t *)(0x4006ED14)) = 0x00000003;
         }
-
-        nrf_usbd_enable();
-
-        // Enable HFCLK
-        hfclk_enable();
+//          CRITICAL_REGION_EXIT();
       }
-    break;
-
-    case POWER_READY:
-      /* 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);
 
       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;
-          }
-
+        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();
       }
 
-      if (nrf_drv_usbd_errata_187())
-      {
+      nrf_usbd_enable();
+
+      // 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);
+
+    if (nrf_drv_usbd_errata_171())
+    {
 //          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();
-      }
+        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;
+        }
 
-      if ( nrf_drv_usbd_errata_166() )
-      {
-        *((volatile uint32_t *) (NRF_USBD_BASE + 0x800)) = 0x7E3;
-        *((volatile uint32_t *) (NRF_USBD_BASE + 0x804)) = 0x40;
+//          CRITICAL_REGION_EXIT();
+    }
 
-        __ISB(); __DSB();
-      }
+    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();
+    }
 
-      nrf_usbd_isosplit_set(NRF_USBD_ISOSPLIT_Half);
+    if ( nrf_drv_usbd_errata_166() )
+    {
+      *((volatile uint32_t *) (NRF_USBD_BASE + 0x800)) = 0x7E3;
+      *((volatile uint32_t *) (NRF_USBD_BASE + 0x804)) = 0x40;
 
-      // 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;
+      __ISB(); __DSB();
+    }
 
-      // 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_isosplit_set(NRF_USBD_ISOSPLIT_Half);
 
-      // 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);
+    // 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;
 
-      // Wait for HFCLK
-      while ( !hfclk_running() ) {}
+    // 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()
 
-      // Enable pull up
-      nrf_usbd_pullup_enable();
-    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);
 
-    case POWER_REMOVE:
-      if ( NRF_USBD->ENABLE )
-      {
-        // Abort all transfers
+    // Wait for HFCLK
+    while ( !hfclk_running() ) {}
 
-        // Disable pull up
-        nrf_usbd_pullup_disable();
+    // Enable pull up
+    nrf_usbd_pullup_enable();
+  }
+  else if (POWER_REMOVE == event )
+  {
+    if ( NRF_USBD->ENABLE )
+    {
+      // Abort all transfers
 
-        // Disable Interrupt
-        NVIC_DisableIRQ(USBD_IRQn);
+      // Disable pull up
+      nrf_usbd_pullup_disable();
 
-        // disable all interrupt
-        NRF_USBD->INTENCLR = NRF_USBD->INTEN;
+      // Disable Interrupt
+      NVIC_DisableIRQ(USBD_IRQn);
 
-        nrf_usbd_disable();
-        hfclk_disable();
-      }
-    break;
+      // disable all interrupt
+      NRF_USBD->INTENCLR = NRF_USBD->INTEN;
 
-    default: break;
+      nrf_usbd_disable();
+      hfclk_disable();
+    }
+  }
+  else
+  {
   }
 }