You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/08/03 15:44:17 UTC

[incubator-nuttx] branch master updated: risc-v/mpfs: usb: configure fifos properly

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new e0291b1ce8 risc-v/mpfs: usb: configure fifos properly
e0291b1ce8 is described below

commit e0291b1ce843e5abcf78364524b6ff7ac0e5f367
Author: Eero Nurkkala <ee...@offcode.fi>
AuthorDate: Wed Aug 3 16:12:49 2022 +0300

    risc-v/mpfs: usb: configure fifos properly
    
    RX_FIFO_ADDRs and TX_FIFO_ADDR were misconfigured. These addresses
    overlapped causing data corruption during high USB loads. For
    example, data corruption was present during the following conditions:
    
      1. Composite USB driver was used (CDC/ACM + Mass storage)
      2. /dev/ttyACM0 was accessed instantly from Linux side when
         starting up.
      3. Training data was sent to /dev/ttyACM0 from NuttX from the
         very beginning periodically.
    
    It was observed that while Mass storage was negotiating, sometimes
    data sent from NuttX to Linux via CDC/ACM was corrupt, although it
    was sent properly on the TX fifo.
    
    Also, don't access TXCSRL_REG_EPN_TX_FIFO_NE_MASK for EP0 as it's
    not applicable.
    
    Signed-off-by: Eero Nurkkala <ee...@offcode.fi>
---
 arch/risc-v/src/mpfs/mpfs_usb.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/arch/risc-v/src/mpfs/mpfs_usb.c b/arch/risc-v/src/mpfs/mpfs_usb.c
index 6590838ab3..471a1fbb99 100755
--- a/arch/risc-v/src/mpfs/mpfs_usb.c
+++ b/arch/risc-v/src/mpfs/mpfs_usb.c
@@ -590,12 +590,15 @@ static void mpfs_write_tx_fifo(const void *in_data, uint32_t length,
 
   /* Poll mode: wait for fifo empty first */
 
-  do
+  if (epno > EP0)
     {
-      tx_csr = getreg16(MPFS_USB_ENDPOINT(epno) +
-                        MPFS_USB_ENDPOINT_TX_CSR_OFFSET);
+      do
+        {
+          tx_csr = getreg16(MPFS_USB_ENDPOINT(epno) +
+                            MPFS_USB_ENDPOINT_TX_CSR_OFFSET);
+        }
+      while (tx_csr & TXCSRL_REG_EPN_TX_FIFO_NE_MASK);
     }
-  while (tx_csr & TXCSRL_REG_EPN_TX_FIFO_NE_MASK);
 
   /* Send 32-bit words first */
 
@@ -1156,8 +1159,6 @@ static void mpfs_ep_set_fifo_size(uint8_t epno, uint8_t in,
 
   if (in)
     {
-      i |= (1 << 4); /* Double buffering */
-
       mpfs_putreg8(i, MPFS_USB_TX_FIFO_SIZE);
     }
   else
@@ -1240,7 +1241,13 @@ static int mpfs_ep_configure_internal(struct mpfs_ep_s *privep,
 
       mpfs_ep_set_fifo_size(epno, 0, maxpacket);
 
-      mpfs_putreg16(desc->addr, MPFS_USB_TX_FIFO_ADDR);
+      /* Give EP0 64 bytes (8*8) and configure 512 bytes for TX fifo.
+       * This is a pointer to internal RAM where the data should be
+       * stored.  It must not overlap with other EPs or it will cause
+       * corruption.  One unit is 8 bytes, so 8 is 8*8 = 64 bytes.
+       */
+
+      mpfs_putreg16(8 + (64 * epno * 2), MPFS_USB_TX_FIFO_ADDR);
 
       /* Disable double buffering */
 
@@ -1280,7 +1287,10 @@ static int mpfs_ep_configure_internal(struct mpfs_ep_s *privep,
                        RXCSRL_REG_EPN_RX_PKT_RDY_MASK);
 
       mpfs_ep_set_fifo_size(epno, dirin, maxpacket);
-      mpfs_putreg16(desc->addr, MPFS_USB_RX_FIFO_ADDR);
+
+      /* Give EP0 64 bytes (8*8) and configure 512 bytes for RX fifo */
+
+      mpfs_putreg16(8 + 64 + (64 * epno * 2), MPFS_USB_RX_FIFO_ADDR);
 
       /* Disable double buffering for RX, will run into trouble with it.
        * The host will send faster than we can handle and all packets