]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
msp430 usci: fix DMA TX byte overwrite
authorR. Steve McKown <rsmckown@gmail.com>
Mon, 29 Dec 2014 23:02:27 +0000 (16:02 -0700)
committerR. Steve McKown <rsmckown@gmail.com>
Mon, 29 Dec 2014 23:02:27 +0000 (16:02 -0700)
The DMA transmit operation for USCI was a little naive, in that it was
not accounting for the possibility that UCxxTXBUF already has a byte to
be transmitted.  Wait for this byte to be transmitted before starting
the DMA operation.

Also note in the code that the DMA transfer operations, trigered by
UCxxTXIFG, are edge sensitive.

tos/chips/msp430/usci/Msp430UartDmaP.nc

index 99a5c91132537a3e178b26313679526698f023f9..d8a59d9707357c21705951cf54b90e452a8a73bd 100644 (file)
@@ -162,15 +162,25 @@ implementation {
       m_solen = len;
     }
 
-    call Registers.clrIfgTx();
-
     /* Configure DMA to transfer m_solen bytes from m_sobuf */
     call DmaChannel.setupTransfer(DMA_SINGLE_TRANSFER, DMAxTSEL_x,
         DMA_EDGE_SENSITIVE, m_sobuf, (void *)UCxxTXBUF_, m_solen, DMA_BYTE,
         DMA_BYTE, DMA_ADDRESS_INCREMENTED, DMA_ADDRESS_UNCHANGED);
-    call DmaChannel.startTransfer();
 
-    /* Set IFGTX to start DMA transfers */
+    /* DMA writes to UCxxTXBUF each time UCxxTXIFG moves from 0 to 1 as its
+     * trigger is edge sensitive.  Therefore, if UCxxTXIFG is already 1,
+     * indicating the UCxxTXBUF is empty, the trigger is not asserted and the
+     * DMA transfer will hang having done nothing.  The solution is a little
+     * kludgy:
+     *
+     * - Wait for UCxxTXBUF to empty
+     * - Manually clear UCxxTXIFG
+     * - Start the DMA transfer (enable the channel trigger)
+     * - Manually set the UCxxTXIFG
+     */
+    while (!(call Registers.getIfgTx()));
+    call Registers.clrIfgTx();
+    call DmaChannel.startTransfer();
     call Registers.setIfgTx();
     return SUCCESS;
   }